APOC importing /retrieve JSON data from CURL


(Artem Nazarenko1990) #1

Problem description: I want to use apoc.load.json , however in a certain manner, namely instead of url or the file path use variable as argument. The reason for this is that I am sending my json as part of CURL, so I can capture it and save to variable, is there some workaround? For instance (unfortunately it doesn't work, as it requires some path and not a JSON object ):

var inputObject = req.body;
var jsonObject = JSON.stringify(inputObject);

.run('WITH $inputParam AS url CALL apoc.load.json(url) ...', {inputParam: jsonObject})

Probably there is some other way to retrieve the json data from curl and to process json in general, besides apoc.

The curl, if it will be helpful:

curl -s -H "Content-Type: application/json" -X POST -d'{"origin":[{"label":"Alcohol drinks", "tag":[], "type":"string", "xpath":[]}, {"label":"Wine", "tag":["red","white"], "type":"string", "xpath":["Alcohol drinks"]}, {"label":"Port wine", "tag":["Portugal","sweet","strong"], "type":"string", "xpath":["Alcohol drinks","Wine"]}, {"label":"Sandeman Cask 33", "tag":["red","expensive"], "type":"string", "xpath":["Alcohol drinks","Wine","Port wine"]}], "target":[{"label":"Drinks", "tag":[], "type":"string", "xpath":[]}, {"label":"Tea", "tag":["black", "green"], "type":"string", "xpath":["Drinks"]}, {"label":"Carbonated water", "tag":[], "type":"string", "xpath":["Drinks","Tea"]}, {"label":"Pepsi", "tag":["sweet","cheap"], "type":"string", "xpath":["Drinks","Tea","Carbonated water"]}]}' http://localhost:3000/ontology

I will appreciate any help. Thank you in advance.

P.S. I also published the same issue on Stackoverflow, link:
https://stackoverflow.com/questions/54892614/apoc-import-extract-json-from-curl


(M. David Allen) #2

The third argument to apoc.load.json can be a "payload" as a string. This is in the body of the HTTP request.

So you can do it by putting your POST into the "payload", but you will have to set headers telling the server how to interpret it, so it will be a little bit fiddly as APOC isn't supposed to be a full HTTP client, but I think you can make it work. To give you a direction to try, go with this -- and adjust depending on how the server responds.

WITH '{ "foo": "bar" }' as jsonDocument
CALL apoc.load.json(url, { "Content-Type": "application/json" }, jsonDocument);

(Artem Nazarenko1990) #3

Thank you for your kind response. My goal is to be able to change the payload dynamically. Probably you can help me. My question is it possible to load json without apoc? Let us say to transmit json data as variable to the body of cypher request, for instance:

var inputObject = req.body;
var jsonObject = JSON.stringify(inputObject);

.run('WITH {inputParam} AS value UNWIND value.origin as or MERGE(label:concept{name:or.label})', {inputParam: jsonObject})

However is throws an error: "Neo4jError: Type mismatch: expected a map but was String"

So my question is, if it is possible to do this in this way - modify String to whatever, and if yes why I get an error. If not possibly, what could be the right solution. as I need, to change the payload dynamically, in other words, changing -d parameter -> receiving on my app -> proceed and insert the "payload" to Neo4j.

I ask you to apologize me, if I am not very clear, as I am quite new to Neo4j.


(M. David Allen) #4

Please edit your post. Your cypher snippet there isn't legal and I think you may have mis-pasted something.

Your example is a tad confusing because you have 2 layers of JSON here. You're using a JS driver to submit the query (that's fine) and that query is using the TEXT of json as a CYPHER parameter. That's also fine, I just need the query to be clear to see what's happening.

I don't see in your example you using APOC anywhere though, which is why you've lost me and I think you've mispasted something.

By passing a parameter to a query as you're starting to do here -- that's a perfectly good approach to making the JSON you're using in Cypher dynamic. Nothing wrong with the concept, I just don't follow your code.


(Artem Nazarenko1990) #5

Thank you for your quick response. In the last example I provided I intentionally left the apoc, as apoc.load need a url parameter. However, in example I found:

https://gist.github.com/jexp/7c6997242c001abfb2cd

something what I was trying to adopt:

.run('UNWIND {inputParam}.origin AS or MERGE(label:concept{name:or.label})', {inputParam: jsonObject})

but still got the same error: Type mismatch: expected a map but was String

From your message I've got that, the problem is exactly in Cypher query, but how can I parse the json data which I pass to a query as a parameter?

Thank you again for your patience.


(Michael Hunger) #6

I'm still not sure what you want to do.

You can just pass your inputObject to your cypher statement as a parameter and then use it within your statement.


(Artem Nazarenko1990) #7

Thank you for your answer and sorry for not being clear. I am trying to do this, namely "pass your inputObject to your cypher statement as a parameter". Here is the cypher statement

.run('UNWIND $inputParam AS param MERGE(label:concept{name:param.origin.label})', {inputParam: jsonObject})

I am using the following tutorial (part with multiply nodes creation):
https://neo4j.com/docs/cypher-manual/current/syntax/parameters/#cypher-parameters-string-literal

Here is the nested json data inside "jsonObject", where I want to create nodes from "origin" and "target":

{"origin":[
{"label":"Alcohol drinks","tag":[],"type":"string","xpath":[]},
{"label":"Wine","tag":["red","white"],"type":"string","xpath":["Alcohol drinks"]},
{"label":"Port wine","tag":["Portugal","sweet","strong"],"type":"string","xpath":["Alcohol drinks","Wine"]},
{"label":"Sandeman Cask 33","tag":["red","expensive"],"type":"string","xpath":["Alcohol drinks","Wine","Port wine"]}],

"target":[
{"label":"Drinks","tag":[],"type":"string","xpath":[]},
{"label":"Tea","tag":["black","green"],"type":"string","xpath":["Drinks"]},
{"label":"Carbonated water","tag":[],"type":"string","xpath":["Drinks","Tea"]}
{"label":"Pepsi","tag":["sweet","cheap"],"type":"string","xpath":["Drinks","Tea","Carbonated water"]}]}

Got an error: Neo4jError: Type mismatch: expected a map but was String

My question is (after clarifying other details): what am I doing wrong, that I am getting this error and could not parse/extract json data using above mentioned Cypher query?

I really do not want to bother you, but probably you could mention some example or point me on my error. Thank you in advance.


(Artem Nazarenko1990) #8

Thank you for your help, the problem was solved. My mistake, as stated, was exactly in the Cypher query. If it will be useful, the link on the answer is here:

https://stackoverflow.com/questions/54892614/apoc-import-extract-json-from-curl/54945339#54945339

Thank you very much again, you helped me a lot.


(Michael Hunger) #9

Happy to help :slight_smile:
Good luck with your project.