【问题标题】:Neo4j Cypher select where exists queryNeo4j Cypher 选择在哪里存在查询
【发布时间】:2020-11-09 21:08:30
【问题描述】:

我有这样的图结构:

我需要选择所有与其他节点有任何连接的ContentItem 节点。

我还传递了每个节点的 id 列表以用于过滤目的。即,我为我希望在搜索中包含的项目传递了一个 neo4j id 列表。与传入 id 的任何其他节点相关的任何 ContentItem 都应返回。

我尝试过使用 UNION,因为这感觉是最简单的方法,但我不确定它是否正确。

MATCH (n:ContentItem) WHERE id(n) IN $neoIds
WITH n
OPTIONAL MATCH (n:ContentItem)-[:IN]->(pt:PulseTopic) WHERE id(pt) IN $pulseTopics RETURN n
UNION
OPTIONAL MATCH (n:ContentItem)-[:IN]->(pst:SubPulseTopic) WHERE id(pst) IN $subPulseTopics RETURN n
UNION
OPTIONAL MATCH (n:ContentItem)-[:FROM]->(s:Supplier) WHERE id(s) IN $suppliers RETURN n
UNION
OPTIONAL MATCH (n:ContentItem)-[:USED_FOR]->(ua:UseArea) WHERE id(ua) IN $useAreas RETURN n
UNION
OPTIONAL MATCH (n:ContentItem)-[:IN]->(blt:BLTopic) WHERE id(blt) IN $blTopics RETURN n

首先,当我在 python 中引用记录时,我得到一个错误:

for r in tx.run(cypherStep2, paramsStep2):
    d = r['n']['id']

...给出:

TypeError: 'NoneType' object is not subscriptable

我不确定为什么会这样。如果我只是做MATCH (n:ContentItem) WHERE id(n) IN $neoIds RETURN n 我不会收到这个错误,所以我认为这与UNION 有关。

其次,我想知道这是否真的会过滤传入的 $neoIds 上的 ContentItem,或者 OPTIONAL MATCH (n:ContentItem) 是否意味着 UNION 中的任何 ContentItem

请问这样查询的最佳方法是什么?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    [更新]

    此查询使用新的existential subquery 功能返回每个ContentItem 节点,其本机ID 在$neoIds 中并具有任何所需的关系:

    MATCH (n:ContentItem)
    WHERE
      ID(n) IN $neoIds AND (
        EXISTS {
          MATCH (n)-[:IN]->(pt:PulseTopic)
          WHERE pt.id IN $pulseTopics}
        OR EXISTS {
          MATCH (n)-[:IN]->(pst:SubPulseTopic)
          WHERE pst.id IN $subPulseTopics}
        OR EXISTS {
          MATCH (n)-[:FROM]->(s:Supplier)
          WHERE s.id IN $suppliers}
        OR EXISTS {
          MATCH (n)-[:USED_FOR]->(ua:UseArea)
          WHERE ua.id IN $useAreas}
        OR EXISTS {
          MATCH (n)-[:IN]->(blt:BLTopic)
          WHERE blt.id IN $blTopics
        }
      )
    RETURN n
    

    这应该比组合多个OPTIONAL MATCH 子句的结果更有效,因为后者将继续搜索(并保存在内存中)所有可能的关系匹配,即使已经找到了一个特定的@987654326 @节点。

    【讨论】:

    • 感谢您的建议。但是,我还需要为每个其他节点类型指定 Neo4j Id。例如$pulseTopics(上图)。此外,可能还有其他关系添加到 ContentItem,因此我不想逐字选择存在任何关系的位置。它需要是与那些特定节点类型的关系。
    • 非常感谢。我会检查一下并回复你。非常感谢。
    【解决方案2】:

    好的,我整理好了。首先,我实际上有一个错误,因为它是 n.id 值而不是传入的 id(n)。

    其次,由于某种未知原因,我得到了一个 None 结果。所以我现在只是在 python 中过滤掉它。

    第三,我似乎需要将id(n) IN $neoIds 放入每个联合查询中。

    这似乎不是最好的解决方案,但它确实有效。如果您有任何改进建议,我会很感兴趣。代码如下:

    OPTIONAL MATCH (n:ContentItem)-[:IN]->(pt:PulseTopic) WHERE pt.id IN $pulseTopics AND id(n) IN $neoIds RETURN n
    UNION
    OPTIONAL MATCH (n:ContentItem)-[:IN]->(pst:SubPulseTopic) WHERE pst.id IN $subPulseTopics AND id(n) IN $neoIds RETURN n
    UNION
    OPTIONAL MATCH (n:ContentItem)-[:FROM]->(s:Supplier) WHERE s.id IN $suppliers AND id(n) IN $neoIds RETURN n
    UNION
    OPTIONAL MATCH (n:ContentItem)-[:USED_FOR]->(ua:UseArea) WHERE ua.id IN $useAreas AND id(n) IN $neoIds RETURN n
    UNION
    OPTIONAL MATCH (n:ContentItem)-[:IN]->(blt:BLTopic) WHERE blt.id IN $blTopics AND id(n) IN $neoIds RETURN n
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-12
      • 1970-01-01
      • 2015-11-01
      • 2017-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多