我正在使用带有 GAP 和 SCENARIO 节点的数据模型的 Neo4j 数据库。每个 GAP 节点都有一个“next”属性,列出所连接的 SCENARIO 节点的键。 SCENARIO 节点有一个“parents”属性,指示它们有多少个父节点。我想根据选定的 GAP 节点列表和父节点数量来过滤 SCENARIO 节点。
以下是 GAP 节点与 SCENARIO 节点的关系:
这是我的 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,则应从结果中排除该场景。如果提供了两个间隙,并且两者都是单个场景的父级,则包括其他场景节点。尽管如此,父条件仅满足该单个节点;它应该只返回单个节点。
我尝试了太多的组合,但总是在某个地方失败。 该查询以某种方式有效,但在以下条件下失败:
我已经被这个问题困扰了大约三天,但一直无法找到解决方案。请注意,根据场景,从 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;
您的样本数据存在不一致。
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;