我在Neo4j中有一个Cypher 1.9.5查询,当用三个索引执行时,它就会挂起。如果我改变查询以使用两个索引和where子句,那么它可以工作(仍然很慢!)
在这个改变的样本中,我正在寻找名称以'tc_'开头的玩具,名称以'2'开头的小盒子,而小盒子的名字以'p'开头
有3个索引挂起
START b=node:BigBox('name:p*'), s=node:SmallBox('name:2*'), ts=node:Toys('name:tc_*')
MATCH b-[:SMALLBOX]->s, s-[:TOYS]->ts
RETURN count(ts)
但这些工作
START s=node:SmallBox('name:2*'), ts=node:Toys('name:tc_*')
MATCH b-[:SMALLBOX]->s, s-[:TOYS]->ts
WHERE b.name =~ '(?i)p.*'
RETURN count(ts)
START b=node:BigBox('name:p*'), ts=node:Toys('name:tc_*')
MATCH b-[:SMALLBOX]->s, s-[:TOYS]->ts
WHERE s.name =~ '(?i)2.*'
RETURN count(ts)
最后两个给出了第一个答案。
在START
子句中允许两个以上的索引需要做什么?请注意,我在90-100个小盒子中有超过200,000个玩具,而这些小盒子又分为5个大盒子。
答案 0 :(得分:3)
你犯了一种叫做笛卡尔积的罪。
正在发生的事情是你正在获取索引查找的所有三组结果:b
,s
和ts
,并且对于每个b,它会找到所有s的结果,对于每组b + s,它找到了所有的b + s + ts。然后,对于每个组合,它找到一个匹配。
解决此问题的更好方法是选择start子句中的最小集合b
,然后使用遍历来查找匹配的潜在s
和ts
。所以:
START b=node:BigBox('name:p*')
MATCH b-[:SMALLBOX]->s
WHERE s.name =~ "2.*"
WITH b, s
MATCH s-[:TOYS]->ts
WHERE ts.name =~ "tc_.*"
RETURN count(ts)