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.
Related
How do I return just the portion of a variable length pattern path that meets some criteria?
In the example below, the following cypher query will return both blue & red nodes.
MATCH p=(a:Person)-[:KNOWS*1..10]->(b:Person)-[:KNOWS]->(j:Person { name: 'Jane'})
RETURN p
However, I want to return the blue nodes that have an incoming relationship confidence_factor >= 0.75. The issue is that everything I've tried either
Eliminates the entire upper mixed blue/red path b/c it's got one rel that fails test
Eliminates just the Jim->Erin rel b/c it fails the test.
Effectively, I want all sequential nodes going backwards from Jane where relationship confidence_factor >= 0.75 but a given path should stop as soon as it encounters a rel that fails that test, and NOT CONTINUE, even if other relationships between nodes in that path might pass (e.g. Tom-[:KNOWS]->Jim)
CREATE (one:Person { name: 'Tom'})
,(two:Person { name: 'Jim'})
,(three:Person { name: 'Erin'})
,(four:Person { name: 'Kevin'})
,(five:Person { name: 'Skylar'})
,(six:Person { name: 'Jane'})
,(one)-[:KNOWS {confidence_factor:0.80}]->(two)
,(two)-[:KNOWS {confidence_factor:0.05}]->(three)
,(three)-[:KNOWS {confidence_factor:0.85}]->(six)
,(four)-[:KNOWS {confidence_factor:0.90}]->(five)
,(five)-[:KNOWS {confidence_factor:0.95}]->(six)
;
You should already get multiple rows with different path lengths. Just look for those paths where all relationships match your criteria.
MATCH p = (:Person {name: 'Jane'})<-[:KNOWS*1..10]-(:Person)
WHERE all(r IN relationships(p) WHERE r.confidence_factor >= 0.75)
RETURN p
If you want to extract the nodes from the path without Jane (remove tail() if you want Jane to be included):
MATCH p = (:Person { name: 'Jane'})<-[:KNOWS*1..10]-(:Person)
WHERE all(r IN relationships(p) WHERE r.confidence_factor >= 0.75)
UNWIND tail(nodes(p)) as person
RETURN DISTINCT person
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" ]
I am new in neo4j, I created a graph following this steps, based on a data model from GTFS. I would like to find all the shortest indirect routes in the graph (with transfers).
Data model of graph database contains 4 entities: Route, Trip, Stop, Stoptime. Here is a screenshot of db.scheme().
Based on query which wrote Bruggen, I modified it for my use:
MATCH
(from:Stop {code:'VBR'})--(st_from:Stoptime),
(to:Stop {code:'VIR'})--(st_to:Stoptime),
p1=((st_from)-[:PRECEDES*]->(st_midway_arr:Stoptime)),
(st_midway_arr)--(midway:Stop),
(midway)--(st_midway_dep:Stoptime),
p2=((st_midway_dep)-[:PRECEDES*]->(st_to))
WHERE
st_from.departure_time > '00:00'
AND st_from.departure_time < '23:00'
AND st_midway_arr.arrival_time > st_from.departure_time
AND st_midway_dep.departure_time > st_midway_arr.arrival_time
AND st_to.arrival_time > st_midway_dep.departure_time
RETURN
from,st_from,to,st_to,p1,p2,midway
order by (st_to.arrival_time_int-st_from.departure_time_int) ASC
limit 1;
This query is not using the shortest path, and it takes in average 30s to find a path, but the output of the query is good.
So I tried to write another query, with method allshortestpaths, it really fast (0,3s). But it returns me also trips which run in a different direction (VIR -> VBR)... another problem is the timing od that connection.
Could you help me, how to access to the transfer node (Station) when I am using allshortestpath method? I want to write a condition for timing and stop_sequence to be sure that's the right direction.
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]-(to))
where NONE (x in relationships(p) where type(x)="OPERATES")
return p
limit 10;
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]->(to)) // here you needed you give the direction to make sure paths are from 'VBR' to 'VIR'
where NONE (x in relationships(p) where type(x)="OPERATES")
return p
limit 10;
Next , if you want to see the nodes in the path , then you can use the nodes(p)
match (from:Stop {code:'VBR'}),(to:Stop {code:'VIR'})
with from,to
match p = allshortestpaths((from)-[*]->(to))
where NONE (x in relationships(p) where type(x)="OPERATES")
AND ALL(node in nodes WHERE node = from OR node = to OR YOUR CONDTION ON TRANSFER NODE)
limit 10
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.
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