Cypher 查询基于 GAP 节点过滤 SCENARIO 节点

问题描述 投票:0回答:1

我正在使用带有 GAP 和 SCENARIO 节点的数据模型的 Neo4j 数据库。每个 GAP 节点都有一个“next”属性,列出所连接的 SCENARIO 节点的键。 SCENARIO 节点有一个“parents”属性,指示它们有多少个父节点。我想根据选定的 GAP 节点列表和父节点数量来过滤 SCENARIO 节点。

以下是 GAP 节点与 SCENARIO 节点的关系:

  • 间隙1键:g1
  • 间隙2键:g2
  • 间隙3键:g3

  • 场景1键:s1
  • 场景2键:s2
  • 场景3键:s3

  • 场景1的父母是:gap1,gap2
  • 场景 2 的父级是:gap1、gap2、gap3
  • 场景 3 的父母是:gap2

这是我的 GAP 和 SCENARIO 节点模型:

 (gap1:GAP {name:  'g1',
            key:   'g1',
            desc:  '',
            next:  's1,s2'
  }),
//GAP2
  (gap2:GAP {name:  'g2',
             key:   'g2',
             desc:  '',
             next:  's1,s2,s3'
  }),
//GAP3
  (gap3:GAP {name:  'g3',
             key:   'g3',
             desc:  'g3',
             next:  's3'
  }),

//SCENARIO
  (scenario1:SCENARIO {name:    's1',
                       key:     's1',
                       DESC:    '',
                       parents: 2
                       }),
  (scenario2:SCENARIO {name:    's2',
                       key:     's2',
                       DESC:    '',
                       parents: 3
                       }),
  (scenario3:SCENARIO {name:    's3',
                       key:     's3',
                       DESC:    '',
                       parents: 1}),

如果在查询中提供了间隙作为输入,并且它是场景的父级,但该场景的父级数量在父节点中大于 1,则应从结果中排除该场景。如果提供了两个间隙,并且两者都是单个场景的父级,则包括其他场景节点。尽管如此,父条件仅满足该单个节点;它应该只返回单个节点。

我尝试了太多的组合,但总是在某个地方失败。 该查询以某种方式有效,但在以下条件下失败:

  1. 当提供g1,g2时,它应该只返回s1。它返回所有三种情况
  2. 如果提供了g1,它应该返回空,但它返回s1,s2
  3. 如果提供了g2,它应该只返回s3,但它返回所有s1,s2,s3

我已经被这个问题困扰了大约三天,但一直无法找到解决方案。请注意,根据场景,从 GAP 到 SCENARIO 的直接链接无法解决问题。

MATCH (gap:GAP)
WHERE gap.name IN ['g1', 'g2', 'g3']

WITH COLLECT(DISTINCT gap) AS selectedGaps

WHERE size(selectedGaps) > 0  

MATCH (scenario:SCENARIO)
WHERE ANY(gap IN selectedGaps WHERE scenario.key IN split(gap.next, ','))
RETURN scenario.name AS ScenarioName;
neo4j cypher
1个回答
0
投票

您的样本数据存在不一致。

  • scenario2
    表示它有 3 个父级,但只有 2 个
    GAP
    节点包含
    s2
    键。
  • scenario3
    表示它有 1 个父级,但有 2 个
    GAP
    节点包含
    s3
    键。

这里是一个应该有效的查询,假设您将数据修复为一致:

MATCH (gap:GAP)
WHERE gap.name IN $gaps
UNWIND SPLIT(gap.next, ',') AS sKey
WITH sKey, COUNT(*) AS cnt
WITH COLLECT({sKey: sKey, cnt: cnt}) AS data
MATCH (s:SCENARIO)
WHERE ANY(d IN data WHERE d.sKey = s.key AND d.cnt = s.parents)
RETURN s.name AS ScenarioName;

查询假定

GAP
名称列表作为
$gaps
参数提供。

推荐新型号

但是,您应该强烈考虑更改您的数据模型。您没有使用任何关系,这是图形数据库的主要优势。

GAP
SCENARIO
节点应通过关系链接。我还建议使用官方 neo4j 命名约定,其中标签采用驼峰式命名。例如,从概念上来说:

(g:Gap {name, key, desc})-[:HAS_SCENARIO]->(s:Scenario {name, key, desc})

此模型不需要

next
parents
属性。

使用这个新模型,您的用例的查询将很简单:

MATCH (g:Gap)-[:HAS_SCENARIO]->(s:Scenario)
WHERE g.name IN $gaps
WITH s, COUNT(g) AS cnt
WHERE COUNT{ ()-[:HAS_SCENARIO]->(s) } = cnt
RETURN s.name AS scenarioName;
© www.soinside.com 2019 - 2024. All rights reserved.