Cypher 对路径感兴趣,您的 MATCH 发现以下内容:
- 通过 Rexter 到项目 3 的 2 条路径(通过项目 2 和 1)
- 通过管道到项目 5 的 2 条路径(通过项目 1 和 2)
- 通过 Rexter 和 Pipes 到项目 4 的 4 条路径(每个人通过项目 1 和 2)
基本上,这些项目会被多次计算,因为每个人通过 Gremlin 的不同常见项目有多个路径可以到达同一项目。
要获得准确的计数,您要么需要匹配不同的 r 用户,然后再匹配 r 用户购买的商品(只要它们不在 Gremlin 购买的商品集合中) , 或者您需要进行整个匹配,但在进行计数之前,请获取关于每个人的不同项目,以便每个人的每个项目仅出现一次......然后获取每个项目的计数(对所有人进行计数)。
这是使用第二种方法的查询
MATCH (n:Person)-[:BOUGHT]->(g_item)
WHERE n.name = 'Gremlin'
WITH n, collect(g_item) as excluded
UNWIND excluded as g_item // now you have excluded list to use later
MATCH (g_item)<-[:BOUGHT]-(r)-[:BOUGHT]->(n_item)
WHERE r <> n AND NOT n_item in excluded
WITH DISTINCT r, n_item
WITH n_item, count(*) as frequency
RETURN n_item.id, frequency
ORDER by frequency DESC
您应该在图表中使用标签,并且应该在查询中使用它们,以便利用索引并快速找到图表中的起点。在您的情况下,:Person(name) 上的索引以及查询中 :Person 标签的使用应该会加快速度,即使更多节点和更多 :Persons 添加到图表中也是如此。
编辑
如果您只是希望查询的简洁性,并且没有足够大的图表来解决性能问题,那么您可以使用原始查询,但添加一行额外的行以获得 @987654324 的不同行@ 和 n_item 在您计算项目之前。这可确保您在计数时仅对每人计数一次。
请注意,它放弃了处理排除项目的优化(它将对每个项目进行模式匹配,而不是聚合已购买项目的集合并进行集合成员资格检查),并且它在进行属性访问而不是进行属性访问时聚合项目只有在节点聚合之后。
MATCH (n:Person)-[:BOUGHT*2]-(r)-[:BOUGHT]->(n_item)
WHERE n.name = 'Gremlin'
WITH DISTINCT n, r, n_item
WHERE NOT (n)-[:BOUGHT]->(n_item)
RETURN n_item.id, count(*) as frequency
ORDER by frequency DESC
我在你的比赛中添加一个快速快捷方式,使用 :BOUGHT*2 表示两个 :BOUGHT 跳跃到r,因为我们并不真正关心中间的项目。