我有一个Neo4j数据库,其关系如下:(:Person)-[:KNOWS]-(:Target)
由于使用Cypher查询,我想删除所有未与至少两个不同目标没有连接的人。
我尝试使用一个查询,该查询针对每个节点获取所有连接的节点(具有任意路径长度),然后计算其中的目标数量。如果少于两个,则删除该节点。 但是请求似乎非常长且不成功:
MATCH (n:Person)
OPTIONAL MATCH (n)-[*]-(t:Target)
WITH n, COUNT(t) AS nb_targets
WHERE NOT n:Target AND nb_targets < 2
RETURN n
由于效率低下,请求甚至无法成功...
注意:我只有几个目标,很多人
答案 0 :(得分:0)
Cypher有兴趣返回与模式匹配的所有可能路径,因此对于像这样的无限制变长查询来说效果不佳。
您可以改为使用path expander procs中的APOC Procedures,其设计用于这些用例更有效。我们甚至可以将每个节点的结果限制为2,因为这是我们需要确定是否需要保留或丢弃节点的最小值。
如果您只需要返回不超过2个目标的查询,则此查询应该有效:
MATCH (n:Person)
WHERE NOT n:TARGET
CALL apoc.path.subgraphNodes(n, {labelFilter:'>TARGET', limit:2, optional:true}) YIELD node
WITH n, count(node) AS nb_targets
WHERE nb_targets < 2
RETURN n
答案 1 :(得分:0)
[已更新]
如果这是现实生活中的情况(例如,确定可能与已知的坏人混为一谈的嫌疑人),那么您可能就不会在意与坏人有较大“隔离度”的人。否则,您可能最终会受到大多数人的怀疑。因此,您可能希望对搜索的深度设置一个合理的上限。
碰巧的是,搜索可变长度路径所需的时间(和内存)会随着搜索深度的增加而呈指数增长,因此要加快搜索速度,您需要对深度范围施加合理的上限搜索也是如此。
因此,请尝试使用合理的上限(例如6)。这是一个查询,用于识别本身不是目标的人,并与(少于6个)目标少于2个的人联系在一起。为了帮助加快搜索速度,我还将搜索限制为仅使用KNOWS
关系(假设这是您关心的唯一关系类型)。并且请注意,由于多个路径可以包含同一目标,因此我计算了DISTINCT
个目标。
MATCH (n:Person) WHERE NOT n:Target
OPTIONAL MATCH (n)-[:KNOWS*..6]-(t:Target)
WITH n, COUNT(DISTINCT t) AS nb_targets
WHERE nb_targets < 2
RETURN n
要消除所有不是潜在犯罪嫌疑人的人(包括距离任何目标至少6个跃点的人),那么您可以首先识别所有犯罪嫌疑人,并删除既不是目标也不是犯罪嫌疑人的人:
MATCH (n:Person) WHERE NOT n:Target
OPTIONAL MATCH (n)-[:KNOWS*..6]-(t:Target)
WITH n, COUNT(DISTINCT t) AS nb_targets
WHERE nb_targets >= 2
WITH COLLECT(n) AS suspects
MATCH (m:Person)
WHERE NOT m:Target AND NOT m IN suspects
DETACH DELETE m