When I make a call to the Neo4j REST API, of the format results = gdb.query(query, data_contents=constants.DATA_GRAPH), I get back many more results, and results that are more complex, than I had expected.
Cypher version: CYPHER 2.2
For example, in a graph that has this arrangement of nodes...
(Bob) --> (Amy) --> (Cal)
... and the query ...
MATCH (n)
OPTIONAL MATCH (a)-[r]-(b)
RETURN DISTINCT n, r
... one of the results returned is as follows:
{ "relationships": [
{ "id":"270"
, "type":"LIKES"
, "startNode":"134"
, "endNode":"136"
, "properties":{}
}
]
, "nodes": [
{ "id":"134"
, "labels":["Person"]
, "properties":{"name":"Amy"}
}
, { "id":"135"
, "labels":["Person"]
, "properties":{"name":"Bob"}
}
, { "id":"136"
, "labels":["Person"]
, "properties":{"name":"Cal"}
}
]
}
If I understand correctly, this indicates a direct relationship between Amy (134) and Cal (136). As far as I can see, Bob has no place in the path between Amy and Cal. So why is Bob appearing in this entry at all?
I also get duplicate entries. For example, this entry appears twice:
{ "relationships": [
{ "id":"264"
, "type":"LIKES"
, "startNode": "134"
, "endNode":"136"
,"properties":{}
}
]
, "nodes": [
{ "id":"134"
, "labels":["Person"]
, "properties":{"name":"Amy"}
}
, { "id":"136"
, "labels":["Person"]
, "properties":{"name":"Cal"}
}
]
}
In my tests, I see rows with 2 or 3 nodes. Is it ever possible to see more nodes in one row? Is it safe to assume that, if a relationship entry includes a startNode and an endNode, that there is a direct link from one to the other, and that any additional nodes that appear in the nodes section for that row can be ignored?
Is there somewhere where I can find a complete explanation of how the graph output is calculated?
Because you have a typo and don't refer to n at all in your optional match.
Also you should use labels!
MATCH (n)
OPTIONAL MATCH (n)-[r]-()
RETURN DISTINCT n, r
Related
I have a JSON response from web service that looks something like this :
[
{
"id":4,
"sourceID":null,
"subject":"SomeSubjectOne",
"category":"SomeCategoryTwo",
"impact":null,
"status":"completed"
},
{
"id":12,
"sourceID":null,
"subject":"SomeSubjectTwo",
"category":"SomeCategoryTwo",
"impact":null,
"status":"assigned"
}
]
What I need to do is extract the subjects from all of the entities by using JSONPATH query.
How can I get these results :
Subject from the first item - SomeSubjectOne
Filter on specific subject value from all entities (SomeSubjectTwo for example)
Get Subjects from all entities
Goessner's orinial JSONPath article is a good reference point and all implementations more or less stick to the suggested query syntax. However, implementations like Jayway JsonPath/Java, JSONPath-Plus/JavaScript, flow-jsonpath/PHP may behave a little differently in some areas. That's why it can be important to know what implementation you are actually using.
Subject from the first item
Just use an index to select the desired array element.
$.[0].subject
Returns:
SomeSubjectOne
Specific subject value
First, go for any elements .., check those with a subject [?(#.subject] and use == '..' for comparison.
$..[?(#.subject == 'SomeSubjectTwo')]
Returns
[ {
"id" : 12,
"sourceID" : null,
"subject" : "SomeSubjectTwo",
"category" : "SomeCategoryTwo",
"impact" : null,
"status" : "assigned" } ]*
Get all subjects
$.[*].subject
or simply
$..subject
Returns
[ "SomeSubjectOne", "SomeSubjectTwo" ]
Suppose my query is :
g.addV('employee').property('id', 'john').property('country', 'USA').property('country', 'India')
which adds property country with two values i.e USA and India.
[
{
"id":"john",
"label":"employee",
"type":"vertex",
"properties":{
"country":[
{
"id":"5dc2aaf6-cb11-4d4a-a2ce-e5fe79d28c80",
"value":"USA"
},
{
"id":"fcf4baf6-b4d5-45a3-a4ba-83a859806aef",
"value":"India"
}
]
}
}
]
Now I want to change one of the existing values. For example 'India' to 'China'.
What will be query for that?
In a single query it's just that:
g.V().has('id', 'john').
sideEffect(properties('country').hasValue('India').drop()).
property(list, 'country', 'China')
We could drop the 'India' value firstly and then add the 'China'. I test it with following query on my side, it works correctly.
g.V().has('id', 'john').properties('country').hasValue('India').drop()
g.V().has('id', 'john').property(list, 'country', 'China')
g.V().has('employee','id', 'john').property('country', 'China')
I'm using GRAPH_TRAVERSAL to get the path from a list of nodes to the head of the tree. This works perfectly except when the example happens to be the head of the tree. In this case, the edgeCollection doesn't have an inbound entry for this object so it doesn't appear in the results.
FOR v IN GRAPH_TRAVERSAL('gdp2',
[{_id:'pmsite/14419285155'}],
'inbound',{edgeCollection:'child'})
RETURN v
The result is an empty list: []
Is there a way I can guarantee that the starting node is on the list? It would be a pain to go through the list of examples to segregate which ones are at the head of a tree.
The problem is within the query itself. It contains a subtle error which is hard to spot:
[{_id:pmsite/14419285155}],
This is missing the quotes around pmsite/14419285155.
What this query realy does is to devide (probably the count of) the collection pmsite by the id 14419285155 and put in this as {_id: divcount}.
If you add the missing quotes, the query should do exactly what you want there. (edit: quotes were present in the original query, fixed the post.)
hint: db._explain() gives information about that.
Trying to reproduce, using the knows sample graph:
arangosh> var examples = require("org/arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("knows_graph");
arangosh> db._query("FOR e IN GRAPH_TRAVERSAL('knows_graph', [{_id: 'persons/eve'}], 'inbound', {edgeCollection: 'knows'}) return e").toArray()
[
[
{
"vertex" : {
"_id" : "persons/eve",
"_rev" : "1405497100114",
"_key" : "eve",
"name" : "Eve"
}
}
]
]
However what creates a somewhat similar behaviour is to use a collection not part of the graph definition:
arangosh> db._create("othercol")
arangosh> db.othercol.save({_key: "1" })
arangosh> db._query("FOR e IN GRAPH_TRAVERSAL('knows_graph', [{_id: 'othercol/1'}], 'inbound', {edgeCollection: 'knows'}) return e").toArray()
[ ]
As pointed out in the Comments, edge relations have a direction. If you want to have edges pointing in both directions, you need to create a second relation in the other direction. Edges not fullfilling the edge definitions may be ignored.
I would like to obtain the longest path that are connected to a single parent via Neo4J Cypher query.
My current queries are like this:
MATCH p=(N1:Node)-[REL*..2]->(N2:Node) WHERE N2.RIC =~"some ticker.*" RETURN p limit 50
However, i am getting results like this
a->b->parent
b-> parent
In my own opinion , i would like to keep only the longest path.
Also, is there anyway to return the direction of the query ? IE: i can see the from/to of a relationship in the output of the query.
Thanking in advance !
If you want just the longest path then you can do:
MATCH path=(N1:Node)-[REL*..2]->(N2:Node)
WHERE N2.RIC =~"some ticker.*"
RETURN p
ORDER BY length(p) DESC
LIMIT 1
As for getting the directions, this depends on the driver that you use. In the Neo4j HTTP transaction endpoint if you specify REST for resultDataContents, it will return a directions for any path objects that you return. Here is how you set that:
http://neo4j.com/docs/stable/rest-api-transactional.html#rest-api-execute-statements-in-an-open-transaction-in-rest-format-for-the-return
Here is an example of what that looks like:
"rest": [
{
"relationships": [
"http://localhost:7474/db/data/relationship/587"
],
"nodes": [
"http://localhost:7474/db/data/node/1002",
"http://localhost:7474/db/data/node/1001"
],
"directions": [
"<-"
],
"length": 1,
"start": "http://localhost:7474/db/data/node/1002",
"end": "http://localhost:7474/db/data/node/1001"
}
]
EDIT:
Responding to your comment, in order to get the longest path for each parent:
MATCH path=(N1:Node)-[REL*..2]->(N2:Node)
WHERE N2.RIC =~"some ticker.*"
WITH N1, N2, collect(p) AS paths
ORDER BY length(p) DESC
RETURN N1, N2, paths[0] AS longest_path
I wasn't sure which side is supposed to be the parent, so I returned both N1 and N2 which should give you the longest path for each combination of those two. You can remove either one to get the longest path leading to/from the node which is left.
I have a record
record = [ [ name1:'value1', name2:'value2', name3:'value3' ],
[ name1:'value6', name2:'value7', name3:'value8' ] ]
I would like to add two more key/value pairs to with values as boolean(true/false) as below
record = [ [ name1:'value1', name2:'value2', name3:'value3', name4:false, name5:true ],
[ name1:'value6', name2:'value7', name3:'value8', name4:false, name5:true ] ]
When I tried to use add or put functions, doesnt seem to work(either replacing the existing values or not doing anything)
Just do:
record = record.collect { it + [ name4:false, name5:true ] }
Or you can also do:
record = record*.plus( name4:false, name5:true )
To add to Patricks answer above (+1), a Map contains a set not a list so all keys must be unique. So you cannot assign multiple values to a single key directly.
Among many solutions, you can alternatively, save an object:
Map<String, myObject>
that holds many different values and this will still maintain the uniqueness of the set since there will only be one key.