My question is why WHERE
operator is not working as fast as expected?
Consider I have 7 nodes with label Consumer
. Here is some sample data...
MERGE (c:Consumer {mobileNumber: "000000000000"})
MERGE (:Consumer {mobileNumber: "111111111111"})
MERGE (:Consumer {mobileNumber: "222222222222"})
MERGE (:Consumer {mobileNumber: "333333333333"})
MERGE (:Consumer {mobileNumber: "444444444444"})
MERGE (:Consumer {mobileNumber: "555555555555"})
MERGE (:Consumer {mobileNumber: "666666666666"})
WITH c
MATCH (c1:Consumer) WHERE c1.mobileNumber <> "000000000000"
MERGE (c)-[:HAS_CONTACT]->(c1)
And there is a HAS_CONTACT
relationship in between :Consumer(mobileNumber:{"000000000000"})
and all other 6 nodes. Also there is a unique index
constraint on mobileNumber
field. Now when I try to execute below query:
PROFILE MATCH (n:Consumer{mobileNumber : "000000000000"}),
(m:Consumer{mobileNumber : "111111111111"})
WITH n,m
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;
So its working fine as expected(Search nodes on the basis of unique index). Below is its result:
Now let change above query using WHERE
clause:
PROFILE MATCH (n:Consumer{mobileNumber : "000000000000"}),
(m:Consumer) WHERE m.mobileNumber
IN (["111111111111"])
WITH n,m
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;
Query Result:
Now although above query is working fine, and giving same result as that of old one. But for endNode where I have used WHERE
clause, it doesn't uses any indexes. It first searches for all existing nodes, and then filter result using WHERE
clause, which can be too expensive if there are hundreds of thousands of nodes with same label.
So my Questions are:
WHERE
clause? IN
operator while expecting index search?As @DaveBennett said, this problem does not seem to exist in version 3.2.2.
If you are using a prior version, try providing hints to the planner that it should use indexing:
PROFILE MATCH
(n:Consumer{mobileNumber : "000000000000"}),
(m:Consumer)
USING INDEX n:Consumer(mobileNumber)
USING INDEX m:Consumer(mobileNumber)
WHERE m.mobileNumber IN (["111111111111"])
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;
This might also work, since some planners seem to automatically attempt to use indexing on (only) the first MATCH
term:
PROFILE MATCH
(n:Consumer{mobileNumber : "000000000000"}),
(m:Consumer)
USING INDEX m:Consumer(mobileNumber)
WHERE m.mobileNumber IN (["111111111111"])
MATCH path = SHORTESTPATH((n)-[contacts:HAS_CONTACT]-(m))
RETURN contacts;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With