WITH子句中的集合扩展为每行一个元素

时间:2018-09-19 08:57:06

标签: neo4j cypher neo4j-apoc

我想创建一个具有节点属性和一些其他信息的地图投影。 我也想在集合中收集一些ID,然后在查询中稍后使用它来滤除节点(其中ID(n)在ID中...)。 地图投影是在apoc调用中创建的,该调用包含多个联合匹配。

call apoc.cypher.run('MATCH (n)-[:IS_A]->({name: "User"}) MATCH (add)-[:IS_A]->({name: "AdditionalInformationForUser"}) RETURN n{.*, info: collect(add.name), id: ID(n)} as nodeWithInfo UNION MATCH (n)-[:IS_A]->({Department}) MATCH (add)-[:IS_A]->({"AdditionalInformationForDepartment"}) RETURN n{.*, info: collect(add.name), id: ID(n)} as nodeWithInfo', NULL) YIELD value
WITH (value.nodeWithInfo) AS nodeWithInfo
WITH collect(nodeWithInfo.id) as nodesWithAdditionalInfosIds, nodeWithInfo
MATCH (n)-[:has]->({"Vacation"})
MATCH (u)-[:is]->({"Out of Order"})
WHERE ID(n) in nodesWithAdditionalInfosIds and ID(u) in nodesWithAdditionalInfosIds
return n, u, nodeWithInfo

这不会返回任何内容,因为在评估where部件时,它不会将“ nodesWithAdditionalInfosIds”检查为平面列表,而是每行仅获得一个id。 该问题仅存在是因为我在WITH子句中传递了id(nodesWithAdditionalInfosIds)和nodeProjection(nodeWithInfo)。

如果我改为仅使用id集合而不使用nodeWithInfo投影,则以下调整有效,并且仅返回ID包含在id集合中的节点:

...
WITH collect(nodeWithInfo.id) as nodesWithAdditionalInfosIds
    MATCH (n)-[:has]->({"Urlaub"})
    MATCH (u)-[:is]->({"Out of Order"})
    WHERE ID(n) in nodesWithAdditionalInfosIds and ID(u) in nodesWithAdditionalInfosIds
    return n, u

如果我只是在两个示例中的WITH子句之后直接返回集合“ nodesWithAdditionalInfosIds”,则这很明显。由于第一个在一个结果行中生成一个平面列表,第二个给我每行一个id。

我感到我缺少关于neo4js With子句的关键知识。 有没有一种方法可以传递我的listOfIds并将其用作平面列表,而无需为该集合使用独占的WITH子句?

编辑: 现在,我正在使用以下解决方法: 完成对ID“ n”和“ u”的检查后,我没有返回,而是保留了经过过滤的“ n”和“ u”节点,并像以前一样开始了第二次apoc调用,该调用返回了“ nodeWithInfo”。

WITH n, u
call apoc.cypher.run('MATCH (n)-[:IS_A]->({name: "User"}) MATCH (add)-[:IS_A]->({name: "AdditionalInformationForUser"}) RETURN n{.*, info: collect(add.name), id: ID(n)} as nodeWithInfo UNION MATCH (n)-[:IS_A]->({Department}) MATCH (add)-[:IS_A]->({"AdditionalInformationForDepartment"}) RETURN n{.*, info: collect(add.name), id: ID(n)} as nodeWithInfo', NULL) YIELD value
WITH (value.nodeWithInfo) AS nodeWithInfo, n, u
WHERE nodeWithInfo.id = ID(n) OR nodeWithInfo.id = ID(u)
RETURN nodeWithInfo, n, u

这样,我可以每行返回节点n,u和附加信息(到一个节点)。但我确信必须有更好的方法。

我知道neo4j中的id必须小心使用(如果有的话)。在这种情况下,我只需要它们在此查询中有效,因此下一次同一节点具有另一个ID无关紧要。

这个问题被归结为核心问题(在我看来),原始查询稍大一些,在apoc内有几个UNION MATCH,并且ID包含在我的集合中的节点上的实际匹配正在检查更多限制而不是要求任何节点。

1 个答案:

答案 0 :(得分:1)

Aggregating functions(类似于COLLECT())在一组“分组键” 上聚合。

  • 在以下子句中:

     WITH collect(nodeWithInfo.id) as nodesWithAdditionalInfosIds, nodeWithInfo
    

    分组密钥为nodeWithInfo。因此,每个nodesWithAdditionalInfosIds总是一个包含一个值的列表。

  • 并在以下子句中:

    WITH collect(nodeWithInfo.id) as nodesWithAdditionalInfosIds
    

    没有分组密钥。因此,在这种情况下,nodesWithAdditionalInfosIds将包含所有nodeWithInfo.id值。