Wednesday, 15 August 2012

neo4j - Cypher / Should I use the WITH clause to pass values to next MATCH? -



neo4j - Cypher / Should I use the WITH clause to pass values to next MATCH? -

using neo4j 2.1.x, let's suppose query, returning user 123's friends bought car:

match (u1:user("123"))-[:knows]-(friend) match (friend)-[:buys]->(c:car) homecoming friend

in article, written regarding with clause:

so, how work? well, stream, lazy can (as lazy homecoming can be), passing results on next query.

so seems should transform query this:

match (u1:user("123"))-[:knows]-(friend) friend match (friend)-[:buys]->(c:car) homecoming friend

should i? or current version of cypher handle match chaining while passing values through them?

the more accurate starting point give in upfront of query, more efficient be.

your first match not accurate, indeed utilize traversal matcher match possible relationships.

taken next neo4j console illustration : http://console.neo4j.org/r/jsx71g

and first query in illustration :

match (n:user { login: 'nash99' })-[:knows]->(friend) homecoming count(*)

you can see amount of dbhits in upfront :

execution plan columnfilter | +eageraggregation | +filter | +traversalmatcher +------------------+------+--------+-------------+-----------------------------------------+ | operator | rows | dbhits | identifiers | other | +------------------+------+--------+-------------+-----------------------------------------+ | columnfilter | 1 | 0 | | maintain columns count(*) | | eageraggregation | 1 | 0 | | | | filter | 8 | 320 | | property(n,login(2)) == { autostring0} | | traversalmatcher | 160 | 201 | | friend, unnamed32, friend | +------------------+------+--------+-------------+-----------------------------------------+ total database accesses: 521

if utilize more accurate starting point, you're king of road when start point, @ illustration query , see difference in db hits :

execution plan columnfilter | +eageraggregation | +simplepatternmatcher | +filter | +nodebylabel +----------------------+------+--------+------------------------+-----------------------------------------+ | operator | rows | dbhits | identifiers | other | +----------------------+------+--------+------------------------+-----------------------------------------+ | columnfilter | 1 | 0 | | maintain columns count(*) | | eageraggregation | 1 | 0 | | | | simplepatternmatcher | 8 | 0 | n, friend, unnamed51 | | | filter | 1 | 40 | | property(n,login(2)) == { autostring0} | | nodebylabel | 20 | 21 | n, n | :user | +----------------------+------+--------+------------------------+-----------------------------------------+ total database accesses: 61

so terminate query, :

match (n:user { login: 'nash99' }) n match (n)-[:knows]->(friend)-[:buys]->(c:car) homecoming friend

you can specify friends can not same user :

match (n:user { login: 'nash99' }) n match (n)-[:knows]->(friend)-[:buys]->(c:car) not friend.id = n.id homecoming friend

note there no difference between above query , next in matter of db hits :

match (n:user { login: 'nash99' }) n match (n)-[:knows]->(friend) friend match (friend)-[:buys)->(c:car) homecoming (friend)

i recommend utilize neo4j console @ result details showing above informations.

if need protoype graph test, can utilize graphgen, export graph in cypher statements , load these statements in neo4j console.

here link graphgen generation used console http://graphgen.neoxygen.io/?graph=29l9xj0hxj2pyq

chris

neo4j cypher

No comments:

Post a Comment