Jonathan Ellithorpe
Jonathan Ellithorpe

Reputation: 564

Neo4j indices slow when querying across 2 labels

I've got a graph where each node has label either A or B, and an index on the id property for each label:

CREATE INDEX ON :A(id);
CREATE INDEX ON :B(id);

In this graph, I want to find the node(s) with id "42", but I don't know a-priori the label. To do this I am executing the following query:

MATCH (n {id:"42"}) WHERE (n:A OR n:B) RETURN n;

But this query takes 6 seconds to complete. However, doing either of:

MATCH (n:A {id:"42"}) RETURN n;
MATCH (n:B {id:"42"}) RETURN n;

Takes only ~10ms.

Am I not formulating my query correctly? What is the right way to formulate it so that it takes advantage of the installed indices?

Upvotes: 0

Views: 63

Answers (3)

CBVgtr
CBVgtr

Reputation: 61

You should use UNION to make sure that both indexes are used. In your question you almost had the answer.

MATCH (n:A {id:"42"}) RETURN n
UNION
MATCH (n:B {id:"42"}) RETURN n
;

This will work. To check your query use profile or explain before your query statement to check if the indexes are used .

Upvotes: 2

cybersam
cybersam

Reputation: 66989

Here is one way to use both indices. result will be a collection of matching nodes.

OPTIONAL MATCH (a:B {id:"42"})
OPTIONAL MATCH (b:A {id:"42"})
RETURN
  (CASE WHEN a IS NULL THEN [] ELSE [a] END) +
  (CASE WHEN b IS NULL THEN [] ELSE [b] END)
  AS result;

You should use PROFILE to verify that the execution plan for your neo4j environment uses the NodeIndexSeek operation for both OPTIONAL MATCH clauses. If not, you can use the USING INDEX clause to give a hint to Cypher.

Upvotes: 2

Tim Kuehn
Tim Kuehn

Reputation: 3251

Indexes are formed and and used via a node label and property, and to use them you need to form your query the same way. That means queries w/out a label will scan all nodes with the results you got.

Upvotes: 1

Related Questions