我对neo4j相当陌生,有时很难理解底层发生了什么。
我想做的主要事情是避免双重查询。因此,我需要把已经看过的合同从第一部分延续到第二部分,这样就不会再看了。
我尝试使用UNION而不是下面描述的COLLECT,但是总的来说速度要慢得多。
我有一个由四个部分组成的查询,像这样(简化):
//PART1
MATCH (x1:X) -[:STARTS_AT]-> (somewhere) <-[:STARTS_AT]- (z1:Z)
MATCH
(x1) -[:ENDS_AT]-> (somewhereelse) <-[:ENDS_AT]- (z1)
WHERE somewhereconditions
WITH COLLECT(x contract_ids) as already_seen_contracts
, COLLECT(all other stuff of interested from x and z) as taking_over
//PART2
MATCH (x2:X) -[:STARTS_AT]-> (somewhere) -[:IS_IN]-> (s2:S),
(x2) -[:ENDS_AT]-> (somewhereelse) -[:IS_IN]-> (e2:S)
path = allshortestpath(s2) CONNECTED (e2)
MATCH (z2:Z) -[:STARTS_AT]-> (somewhere) -[:IS_IN]-> (r:S),
(z2) -[:ENDS_AT]-> (somewhereelse) -[:IS_IN]-> (t:S)
WHERE z2 on path
AND x2.contracts not in already_seen_contracts
WITH already_seen + COLLECT(x contract_ids) as already_seen
, taking_over + COLLECT(all other stuff of interested from x and z) as taking_over
//PART3 and PART4 similar
UNWIND taking_over AS taking_over_unwind
RETURN stuff from taking_over_unwind
我希望我笨拙的简化尝试能使我所使用的结构清晰。我的想法是,在每个部分中使用COLLECT,我创建了一种容器,我可以从每个部分添加新的东西(使用第一个COLLECT和NOT in过滤器来避免双重查询,我首先以这种方式设置它),将其转移到下一个部分并最终返回所有结果。
只要每个部分都有结果就可以。
现在有一部分是空的(其他部分不是),整个查询在最后根本不返回任何东西。我有点期望它仍然会返回在非空部分中找到的东西。
我尝试了OPTIONAL MATCH,但这不是一个选项,因为我明确不希望返回null,例如在part1中的第二个MATCH中。
我已经看到了一个使用虚拟节点的解决方案,我必须每次将其添加到COLLECT中以确保至少有一个结果?
任何关于如何避免双重查询本身或解决上述问题的想法,其中null使所有结果消失,高度赞赏!
还有:为什么会发生这种情况?
非常感谢你的帮助!
编辑:样本数据:拥有某种类型的节点X和具有属性的另一种类型的节点Z,并进行收缩和创建。
我想把所有的
x1。contractids z1。contractids, x1。createdates, z1.createdates
x2。contractids z2。contractids x2。createdates, z2.createdates
'1s' x和z有相同的起点和终点,因为'2s' z沿着x的路线。
试着分析你的查询,像这样:
PROFILE MATCH (x1:X) -[:STARTS_AT]-> (somewhere) <-[:STARTS_AT]- (z1:Z)
MATCH
(x1) -[:ENDS_AT]-> (somewhereelse) <-[:ENDS_AT]- (z1)
WHERE somewhereconditions
WITH COLLECT(x contract_ids) as already_seen_contracts
, COLLECT(all other stuff of interested from x and z) as taking_over
MATCH (x2:X) -[:STARTS_AT]-> (somewhere) -[:IS_IN]-> (s2:S),
(x2) -[:ENDS_AT]-> (somewhereelse) -[:IS_IN]-> (e2:S)
path = allshortestpath(s2) CONNECTED (e2)
MATCH (z2:Z) -[:STARTS_AT]-> (somewhere) -[:IS_IN]-> (r:S),
(z2) -[:ENDS_AT]-> (somewhereelse) -[:IS_IN]-> (t:S)
WHERE z2 on path
AND x2.contracts not in already_seen_contracts
WITH already_seen + COLLECT(x contract_ids) as already_seen
, taking_over + COLLECT(all other stuff of interested from x and z) as taking_over
UNWIND taking_over AS taking_over_unwind
RETURN stuff from taking_over_unwind
您将获得查询的查询执行图。请注意,在内部,neo4j以rows
的形式将数据从一个阶段传递到另一个阶段,因此当在一个阶段中由于某些条件检查而过滤掉所有rows
时,前面的阶段将不做任何事情,结果集将为空。
在您的例子中,您可以做的是将查询分解为多个部分。传递您希望在其他查询中重用的节点的primary key
或unique identifiers
,并在唯一标识符上创建一些索引。通过这种方式,性能将不是问题,并且您将从不同部分获得预期的输出,这些部分可以在应用程序级别进行组合。