Neo4j:有人可以 "translate" 这个代码片段给我吗?
Neo4j: Could someone "translate" this code snippet for me?
如果我没有遵循这里的最佳实践,我很抱歉,但我无法理解(因此当然也不会在新版本的 Neo4j 中重新创建)这个片段应该做什么:(
出于兴趣,我开始了我的 Neo4j 之旅并结束了介绍 类 并想重新创建一些项目以更加熟练地使用这项有趣的技术。
但是我无法从“What's cooking”示例中了解这个练习:
// Construct lists of node ids of ingredients,
// grouped by node ids of recipes
MATCH (r:Recipe)-[:CONTAINS_INGREDIENT]->(ingredient)
WITH {item:id(r), categories: collect(id(ingredient))} as userData
WITH collect(userData) as data
CALL algo.similarity.jaccard.stream(data)
YIELD item1, item2, count1, count2, intersection, similarity
// Look up nodes by node id
WITH algo.asNode(item1) AS from,
algo.asNode(item2) AS to,
similarity, intersection
RETURN from.name, from.id, to.name, to.id, intersection, similarity
ORDER BY similarity DESC
LIMIT 20
当我尝试用 gds.nodeSimilarity.stream 和 [= 更新过时的 algo.similarity.jaccard() 24=]algo.asNode() 和 gds.asNode(),我在 YIELD 之后仍然失败控制台告诉我的语句,它只是找不到 item1(因此也找不到 item2)。
编辑:我是 运行 Neo4j 版本 4.2.5 和 GDS 1.5.2
我希望有人能帮助我了解哪里出了问题!
BR,
旦
你是对的,你的例子来自旧的算法库,而不是当前的 GDS 库。以下是示例代码的功能细分。
首先将食谱与其所含成分相匹配。
// Construct lists of node ids of ingredients,
// grouped by node ids of recipes
MATCH (r:Recipe)-[:CONTAINS_INGREDIENT]->(ingredient)
此时,我们有一个 tall 结果集,由一对 r
个食谱节点和 ingredient
个成分节点组成。
WITH {item:id(r), categories: collect(id(ingredient))} as userData
现在我们已经转换了结果,所以每个配方都有一张地图。该地图有两个 key-value 对。 item
键指向配方节点的 ID。 categories
键指向成分节点的所有 ID 的列表。
WITH collect(userData) as data
我们再次将结果从每行一张地图的多行转换为单行。该行包含一个名为 data
的列表,其中包含所有地图。这是 algo.similarity.jaccard.stream 期望作为输入的格式。现在我们可以调用算法了。
CALL algo.similarity.jaccard.stream(data)
YIELD item1, item2, count1, count2, intersection, similarity
算法输出item1和item2。这些是 Neo4j 的内部节点 ID。这些 id 在 Neo4j 之外没有意义,所以我们想通过调用 algo.asNode
将它们转换回节点
// Look up nodes by node id
WITH algo.asNode(item1) AS from,
algo.asNode(item2) AS to,
similarity, intersection
现在我们可以return我们感兴趣的节点属性。
RETURN from.name, from.id, to.name, to.id, intersection, similarity
ORDER BY similarity DESC
LIMIT 20
要在当前的 Graph Data Science 库中做类似的事情,您可以使用 Node Similarity algorithm。 GDS 算法不是期望地图列表,而是接受 in-memory 图形投影作为输入。创建一个名为 recipe-graph
的 in-memory 图,其中包含 Recipe
和 Ingredient
节点以及 CONTAINS_INGREDIENT
关系。
CALL gds.graph.create('recipe-graph', ["Recipe", "Ingredient"], 'CONTAINS_INGREDIENT')
然后,将该图传递给 nodeSimilarity
算法。
CALL gds.nodeSimilarity.stream('recipe-graph')
YIELD node1, node2, similarity
WITH gds.util.asNode(node1) AS r1,
gds.util.asNode(node2) AS r2, similarity
WHERE r1:Recipe and r1:Recipe
RETURN r1.name as recipe1, r2.name as recipe2, similarity
ORDER BY similarity DESCENDING, r1.name, r2.name
LIMIT 20
最后,放下您创建的 in-memory 图表。
CALL gds.graph.drop('recipe-graph')
如果您不想创建和删除命名图,也可以在 anonymous graph.
上调用算法
如果我没有遵循这里的最佳实践,我很抱歉,但我无法理解(因此当然也不会在新版本的 Neo4j 中重新创建)这个片段应该做什么:(
出于兴趣,我开始了我的 Neo4j 之旅并结束了介绍 类 并想重新创建一些项目以更加熟练地使用这项有趣的技术。 但是我无法从“What's cooking”示例中了解这个练习:
// Construct lists of node ids of ingredients,
// grouped by node ids of recipes
MATCH (r:Recipe)-[:CONTAINS_INGREDIENT]->(ingredient)
WITH {item:id(r), categories: collect(id(ingredient))} as userData
WITH collect(userData) as data
CALL algo.similarity.jaccard.stream(data)
YIELD item1, item2, count1, count2, intersection, similarity
// Look up nodes by node id
WITH algo.asNode(item1) AS from,
algo.asNode(item2) AS to,
similarity, intersection
RETURN from.name, from.id, to.name, to.id, intersection, similarity
ORDER BY similarity DESC
LIMIT 20
当我尝试用 gds.nodeSimilarity.stream 和 [= 更新过时的 algo.similarity.jaccard() 24=]algo.asNode() 和 gds.asNode(),我在 YIELD 之后仍然失败控制台告诉我的语句,它只是找不到 item1(因此也找不到 item2)。
编辑:我是 运行 Neo4j 版本 4.2.5 和 GDS 1.5.2
我希望有人能帮助我了解哪里出了问题!
BR, 旦
你是对的,你的例子来自旧的算法库,而不是当前的 GDS 库。以下是示例代码的功能细分。
首先将食谱与其所含成分相匹配。
// Construct lists of node ids of ingredients,
// grouped by node ids of recipes
MATCH (r:Recipe)-[:CONTAINS_INGREDIENT]->(ingredient)
此时,我们有一个 tall 结果集,由一对 r
个食谱节点和 ingredient
个成分节点组成。
WITH {item:id(r), categories: collect(id(ingredient))} as userData
现在我们已经转换了结果,所以每个配方都有一张地图。该地图有两个 key-value 对。 item
键指向配方节点的 ID。 categories
键指向成分节点的所有 ID 的列表。
WITH collect(userData) as data
我们再次将结果从每行一张地图的多行转换为单行。该行包含一个名为 data
的列表,其中包含所有地图。这是 algo.similarity.jaccard.stream 期望作为输入的格式。现在我们可以调用算法了。
CALL algo.similarity.jaccard.stream(data)
YIELD item1, item2, count1, count2, intersection, similarity
算法输出item1和item2。这些是 Neo4j 的内部节点 ID。这些 id 在 Neo4j 之外没有意义,所以我们想通过调用 algo.asNode
// Look up nodes by node id
WITH algo.asNode(item1) AS from,
algo.asNode(item2) AS to,
similarity, intersection
现在我们可以return我们感兴趣的节点属性。
RETURN from.name, from.id, to.name, to.id, intersection, similarity
ORDER BY similarity DESC
LIMIT 20
要在当前的 Graph Data Science 库中做类似的事情,您可以使用 Node Similarity algorithm。 GDS 算法不是期望地图列表,而是接受 in-memory 图形投影作为输入。创建一个名为 recipe-graph
的 in-memory 图,其中包含 Recipe
和 Ingredient
节点以及 CONTAINS_INGREDIENT
关系。
CALL gds.graph.create('recipe-graph', ["Recipe", "Ingredient"], 'CONTAINS_INGREDIENT')
然后,将该图传递给 nodeSimilarity
算法。
CALL gds.nodeSimilarity.stream('recipe-graph')
YIELD node1, node2, similarity
WITH gds.util.asNode(node1) AS r1,
gds.util.asNode(node2) AS r2, similarity
WHERE r1:Recipe and r1:Recipe
RETURN r1.name as recipe1, r2.name as recipe2, similarity
ORDER BY similarity DESCENDING, r1.name, r2.name
LIMIT 20
最后,放下您创建的 in-memory 图表。
CALL gds.graph.drop('recipe-graph')
如果您不想创建和删除命名图,也可以在 anonymous graph.
上调用算法