在对持续更新的数据使用 algo.similarity.jaccard 时防止重复的 SIMILAR 关系

Preventing duplicate SIMILAR relationships when using algo.similarity.jaccard on continuously updated data

我正在使用 Neo4j 图形算法库中的 algo.similarity.jaccard 算法计算图形中一类节点的 Jaccard 相似性指数。计算 Jaccard 相似度并指示截止值后,我将度量存储在节点之间的关系中(这是算法的一个特征)。当我将新数据添加到图表中时,我试图查看图表随时间的变化(我将使用新数据重新加载我的 CSV 文件并合并到新的 nodes/relationships)。

我预见到的一个问题是,一旦我使用更新后的图形再次 运行 Jaccard 算法,它将创建重复的关系。这是我正在使用的代码的 Neo4j 文档示例:

MATCH (p:Person)-[:LIKES]->(cuisine)
WITH {item:id(p), categories: collect(id(cuisine))} as userData
WITH collect(userData) as data
CALL algo.similarity.jaccard(data, {topK: 1, similarityCutoff: 0.1, write:true})
YIELD nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, stdDev, p25, p50, p75, p90, p95, p99, p999, p100
RETURN nodes, similarityPairs, write, writeRelationshipType, writeProperty, min, max, mean, p95

有没有一种方法可以指定我不想每次 运行 使用更新的图表的代码时都有重复的关系?手动地,我会使用 MERGE 而不是 CREATE,但看起来好像这是一个来自库的算法,我不确定如何去做。仅供参考,我将无法向库插件添加更改,而且似乎无法将关系存储在不同的标签下,例如 SIMILARITY2。

至少有两种方法可以避免多次调用 algo.similarity.jaccard:

的重复关系
  1. 在每次调用之前删除现有关系(默认情况下,它们具有 SIMILAR 类型)。这可能是最简单的方法。

  2. 在进行调用时省略 write:true 选项(这样该过程根本不会创建关系),并编写您自己的 Cypher 代码以选择性地创建尚未创建的关系存在(使用 MERGE)。

[更新]

这是第二种方法的示例(使用 algo.similarity.jaccard.stream 过程的变体,它为我们的目的产生更有用的值):

MATCH (p:Person)-[:LIKES]->(cuisine)
WITH {item:id(p), categories: collect(id(cuisine))} as userData
WITH collect(userData) as data
CALL algo.similarity.jaccard.stream(data, {topK: 1, similarityCutoff: 0.1})
YIELD item1, item2, similarity
WHERE item1 < item2
WITH algo.getNodeById(item1) AS n1, algo.getNodeById(item2) AS n2, similarity
MERGE (n1)-[s:SIMILAR]-(n2)
SET s.score = similarity
RETURN *

由于程序将return相同的节点对两次(具有相同的similarity分数),WHERE子句用于过滤掉其中一对,以加快上处理。 algo.getNodeById() 效用函数用于通过节点的本机 ID 获取节点。并且 MERGE 子句的关系模式没有为 score 指定值,因此它会匹配现有关系,即使它具有不同的值。用于设置 scoreSET 子句位于 之后 MERGE,这也有助于确保值是最新的。