Neo4j new cypher format of relationship pattern - neo4j

The relationship pattern in queries is changing, but the documentation is lacking. I get a "pending depreciation" message when writing this query:
match path = (p:Person)-[r:father|mother*0..5]->(a:Person)
return path limit 25
How do I write this to confirm to the new requirements?
It needs to be something like this but with some portion of the father|mother*0..5 moved into the relationships(path)
match path = (p:Person)-[r:father|mother*0..5]->(a:Person)
with *, relationships(path) as r
return path limit 25
That query runs okay but the error message persists.
What is the proper new format?

I assume Neo4j is complaining about the r . Can you try this:
match path = (p:Person)-[:father|mother*0..5]->(a:Person)
with *, relationships(path) as r
return path limit 25
The more complex case i would suggest to split the match
match path1= (p:Person{RN:5242})-[:father|mother*0..15]->(mrca:Person),
path2= (mrca)<-[:father|mother*0..15]-(b:Person{RN:1}) return length(path1), length(path2)

Related

Neo4J optimize path generation query

How to make the query below work seconds instead of minutes?
I'm new to graph databases. Am I right if I say that node indexing won't help to speed up my query? As I understand, indexes helps to find start point of traversal, not for traversing itself.
May relationship indexing be helpful in my case?
Query
I have 2,500 nodes of type COLUMN and 52,000 relationships between nodes.
The query below is too slow, I even don't know how slow is it. It takes more than 5 minutes, than I get java.net.SocketTimeoutException.
Query
MATCH path = (start:PERSON)-[r:MET_REL*2..5]->(person:PERSON)
WHERE start.ID = '385'
WITH path UNWIND NODES(path) AS col
WITH path,
COLLECT(DISTINCT col.COUNTRY_ID) as distinctCountries
WHERE LENGTH(path) + 1 = SIZE(distinctCountries)
RETURN path
P.S.
Moreover, I want to do [r:MET_REL*2..25] instead of [r:MET_REL*2..5]
Make sure you have an index/constraint on :PERSON(ID)
Please try this:
MATCH path = (start:PERSON)-[:MET_REL*2..5]->(person:PERSON)
WHERE start.ID = '385'
WITH path, reduce(a=[], n in nodes(path) | case when n.COUNTRY_ID IN a then a else a + [n.COUNTRY_ID] end) as countries
WHERE LENGTH(path) + 1 = SIZE(distinctCountries)
RETURN path
With APOC there is an apoc.coll.toSet function that you could use on the countries.

Cypher query to find the longest path using neo4j 3.1.0 version

Can anybody send the Cypher query to find LONGEST PATH between two nodes using neo4j 3.1.0 version.
The graph algorithm to find the longest path is not implemented.
Here is a Cypher query that gets all paths and sorts them by size:
// get the nodes
MATCH (a:Node), (b:Node)
WHERE ID(a) = 14 AND ID(b) = 7
WITH a,b
// match all paths
MATCH p=(a)-[*]-(b)
// return the longest
RETURN p, length(p) ORDER BY length(p) DESC LIMIT 1
However, without any restrictions on the query, this might not work on large graphs. Finding the longest path in an undirected graph is expensive: https://en.wikipedia.org/wiki/Longest_path_problem
And without restrictions on the query (direction and relationship type) the query will look for all undirected paths.
You should restrict your path query or try two solve your problem without the longest path.
If you are looking for the longest path between nodes where each node in the chain has the same relationship to the next then see Achieving longestPath Using Cypher which shows:
MATCH p=(parent:Entity)-[:HAS_CHILD*1..10]->(child:Person)
WHERE size((child)-[:HAS_CHILD]->()) = 0
RETURN child;
However I am using:
MATCH (parent:Entity)-[:HAS_CHILD*1..10]->(child:Person)
WHERE NOT (child)-[r:HAS_CHILD]->()
RETURN child;
If anyone can comment on performance or any other aspect please do!
I also discovered an undocumented feature which will return the child when it is also the parent (as in only one node):
MATCH (parent:Entity)-[:HAS_CHILD*0..]->(child:Person)
WHERE NOT (child)-[r:HAS_CHILD]->()
RETURN child;

Find shortest path between nodes with additional filter

I'm trying to model flights between airports on certain dates. So far my test graph looks like this:
Finding shortest path between for example LTN and WAW is trivial with:
MATCH (f:Airport {code: "LTN"}), (t:Airport {code: "WAW"}),
p = shortestPath((f)-[]-(t)) RETURN p
Which gives me:
But I have no idea how to get only paths with Flights that have relation FLIES_ON with given Date.
Link to Neo4j console
Here's what I would do with your given model. The other commenters' queries don't seem right, as they use ANY() instead of ALL(). You specifically said you only want paths where all Flight nodes on the path are attached to a given Date node with a :FLIES_ON relationship:
MATCH (LTN:Airport {code:"LTN"}),
(WAW:Airport {code:"WAW"}),
p =(LTN)-[:ROUTE*]-(WAW)
WHERE ALL(x IN FILTER(x IN NODES(p) WHERE x:Flight)
WHERE (x)<-[:FLIES_ON]-(:Date {date:"130114"}))
WITH p ORDER BY LENGTH(p) LIMIT 1
RETURN p
http://console.neo4j.org/r/xgz84y
though this would not be my preferred structure for this kind of data; in answering your question i might go this way instead. get the paths, filter the path and get the first one ordered by length.
in the console tests is runs faster than the one suggested above as the query plan is simpler.
Anyhoo i hope this at least points you in a good direction :)
MATCH (f:Airport { cd: "ltn" }),(t:Airport { cd: "waw" }), p =((f)-[r*]-(t))
WHERE ANY (x IN relationships(p)
WHERE type(x)='FLIES_ON') AND ANY (x IN nodes(p)
WHERE x.cd='130114')
RETURN p
ORDER BY length(p)
LIMIT 1
The problem is that using shortestPath or allShortestPaths will never include the Date nodes.
What you need to do is to filter the pattern with the date node (I don't know however how you store the date, so I'll take Ymd format:
MATCH (f:Airport {code: "LTN"}), (t:Airport {code: "WAW"})
MATCH p=(f)-[*]-(t)
WHERE ANY (r in rels(p) WHERE type(r) = 'FLIES_ON')
AND ANY (n in nodes(p) WHERE 'Date' IN labels(n) AND n.date = 20150120)
RETURN p
ORDER BY length(p)
LIMIT 1
Another solution and less costly, is to include the date in your match and building yourself the path with it :
MATCH (n:Date {date:20150120})
MATCH (f:Airport {code:"LTN"}), (t:Airport {code:"WAW"})
MATCH p=(f)<-[*]-(n)-[*]->(t)
RETURN distinct(p)
ORDER BY length(p)

Limiting number of paths the query search in cypher query other than limit

I want the query to stop as soon as it finds first 10 paths and return those.
But by default the limit clause finds all the paths and then just returns first 10 paths.
Because total paths in my case will be around 10k to 20k, its not practical to do that.
i tried following two queries which dont work
match path = (first:Job)-[:PRECEDES*]->(last:Job)
where first.name = 'xyz' and last.name = 'abc'
return nodes(path) as pathlist
match path1 = (first:Job)-[:PRECEDES*]->(middle:Job)
where first.name = 'xyz'
with middle, path1
match path2 = (middle:Job)-[:PRECEDES*]->(last:Job)
last.name = 'abc'
return nodes(path1),nodes(path2) as pathlist
both are taking forever to complete.
Be sure to have an index in place:
CREATE INDEX ON :Job(name)
By inspecting the statements using PROFILE in neo4j-shell I've found the following being the cheapest variant:
MATCH (a:Job {name:'xyz'}), (b:Job {name:'abc'})
MATCH path=(a)-[:PRECEDES*]->(b)
RETURN nodes(path) LIMT 10
Please note that I'm talking of Neo4j 2.1.6. Since Cypher's implementation is steadily evolving, a upcoming version might already optimize your statements appropriately.

Neo4j: Expres path cypher query result in terms of nodes

I have the following node structure Emp[e_id, e_name, e_bossid]. What is more I have a recursive query that exploit the database in recursive traversal on SELF relation e_bossid-[REPORTS_TO]->e_id
MATCH (e:Employee) WHERE NOT (e)-[:REPORTS_TO]->()
SET e:Root;
MATCH path = (b:Root)<-[:REPORTS_TO*]-(e:Employee)
RETURN path
limit 1000;
However the result is PATH. I would like to have result in form of NODES not the path. I tried to use the nodes(path), but it gives me an error:
org.codehaus.jackson.map.JsonMappingException: Reference node not available (through reference chain: java.util.ArrayList[0]->java.util.HashMap["rel"]->java.util.HashMap["nodes(path)"]->java.util.ArrayList[0]->org.neo4j.rest.graphdb.entity.RestNode["restApi"]->org.neo4j.rest.graphdb.RestAPIFacade["direct"]->org.neo4j.rest.graphdb.ExecutingRestAPI["referenceNode"])
When I query without nodes(path) it seems to return only paths.
How this should be done on the ground of cypher query?
I'm not sure why you would want to get all possible paths in your organizational hierarchy. Maybe what you want to get is a set of paths from the leaves of the tree to the root of the tree, and to return each unique set as a row of nodes.
MATCH (b:Employee)
WHERE NOT (b)-[:REPORTS_TO]->()
MATCH (l:Employee)
WHERE NOT (l)<-[:REPORTS_TO]-()
MATCH p = shortestPath((b)<-[:REPORTS_TO*]-(l))
RETURN nodes(p) as reports
As far as your error goes, that looks like a bug, although I don't know what version of Neo4j you are using. In all likelihood, your query won't complete because your Root employees are still a member of the Employee label. Which means that this pattern: MATCH path = (b:Root)<-[:REPORTS_TO*]-(e:Employee) matches the Root employees on each side of the variable length traversal.
Give my query a try and let me know what happens.

Resources