H. Trujillo
H. Trujillo

Reputation: 437

Most efficient way to get result from Neo4j

I need to return a node and all the nodes associated with it based on a relationship. An example of the query would be like:

MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH p=(n)-[:OWNS]->(q)

Would it be more efficient to get node 'n' on its own and then get the paths in a separate call, or should I do a callthat returns 'n' and 'p'.

Addt. information: I have to do this for multiple relationships and I have noticed that every time I add a relationship, the combinatorics between all the paths causes the performance to deteriorate. Example:

MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH p=(n)-[:OWNS]->(q:Something)
OPTIONAL MATCH o=(n)-[:USES]->(r:SomethingElse)
.
.
.
OPTIONAL MATCH l=(n)-[:LOCATED_IN]->(r:NthSomethingElse)
RETURN n, p, o,..., l

or

//Call 1
MATCH (n) where id(n)= {neo_id}
RETURN n

//Call 2
MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH p=(n)-[:OWNS]->(q:Something)
RETURN p

//Call 3
MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH o=(n)-[:USES]->(r:SomethingElse)
RETURN o
.
.
.
//Call nth
MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH l=(n)-[:LOCATED_IN]->(r:NthSomethingElse)
RETURN l

Upvotes: 0

Views: 60

Answers (1)

cybersam
cybersam

Reputation: 67009

If you always want to get n (if it exists), even if it has no relationships, then your first query is really the only way to do that. If you don't want that, then combining the 2 clauses into 1 probably has little impact on performance.

The reason you notice a slow down every time you add another MATCH is because of "cartesian products". That is: if a MATCH or OPTIONAL MATCH clause would "normally" produce N rows of data, but previous clauses in the same query had already produced M rows of data, the actual resulting number of rows would be M*N. So, every extra MATCH has a multiplicative effect on the number of data rows.

Depending on your use case, you might be able to avoid cartesian products by using aggregation on the results of all (or hopefully most) MATCH clauses, which can turn N into 1 (or some other smaller number). For example:

MATCH (n) where id(n)= {neo_id}
OPTIONAL MATCH p=(n)-[:OWNS]->(:Something)
WITH n, COLLECT(p) AS owns
OPTIONAL MATCH o=(n)-[:USES]->(:SomethingElse)
WITH n, owns, COLLECT(o) AS uses
OPTIONAL MATCH l=(n)-[:LOCATED_IN]->(:NthSomethingElse)
WITH n, owns, uses, COLLECT(l) AS located_in
RETURN n, owns, uses, located_in;

Upvotes: 2

Related Questions