如何在Neo4j中编写含NOT/OR逻辑的Cypher查询
问题:Neo4j Cypher查询逻辑不符合预期
我需要在Neo4j中执行如下逻辑的查询,但当前编写的Cypher未得到正确结果:
NOT((service 由 Adani Transmission Limited 提供 AND service 地址在 Formosa) OR service 依赖 Video interview data)
以下是我编写的Cypher查询:
MATCH (node:service )-[provid_by]->(dst:provider) WITH DISTINCT node, COLLECT(DISTINCT TOLOWER(dst.name)) AS names WHERE NONE(name IN names WHERE name IN ["adani transmission limited"]) OR size(names) = 0 WITH DISTINCT node RETURN DISTINCT node UNION MATCH (node:service )-[address_in]->(dst:Address) WITH DISTINCT node, COLLECT(DISTINCT TOLOWER(dst.name)) AS names WHERE NONE(name IN names WHERE name IN ["formosa"]) OR size(names) = 0 WITH DISTINCT node MATCH (node:service)-[depen_on]->(dst:res) WITH DISTINCT node, COLLECT(DISTINCT TOLOWER(dst.name)) AS names WHERE NONE(name IN names WHERE name IN ["video interview data"]) OR size(names) = 0 WITH DISTINCT node WITH DISTINCT node ORDER BY node.createdAt DESC RETURN DISTINCT node UNION MATCH (node:service) WHERE NOT (node)-[:provid_by]->(:Participant) WITH DISTINCT node RETURN DISTINCT node UNION MATCH (node:service) WHERE NOT (node)-[:address_in]->(:Address) WITH DISTINCT node RETURN DISTINCT node UNION MATCH (node:service) WHERE NOT (node)-[:depen_on]->(:res) WITH DISTINCT node RETURN DISTINCT node
解决方案
你的现有查询用多个UNION合并结果,逻辑和需求完全不符——需求是要排除同时满足「由Adani提供+地址在Formosa」或者依赖Video interview data的服务,应该用统一的条件过滤实现,而非拆分多个查询合并。
正确的Cypher查询如下:
MATCH (node:service) // 可选匹配服务的提供商,兼容无提供商的服务节点 OPTIONAL MATCH (node)-[:provid_by]->(provider:provider) WITH node, COLLECT(DISTINCT TOLOWER(provider.name)) AS providerNames // 可选匹配服务的地址,兼容无地址的服务节点 OPTIONAL MATCH (node)-[:address_in]->(addr:Address) WITH node, providerNames, COLLECT(DISTINCT TOLOWER(addr.name)) AS addressNames // 可选匹配服务依赖的资源,兼容无依赖的服务节点 OPTIONAL MATCH (node)-[:depen_on]->(res:res) WITH node, providerNames, addressNames, COLLECT(DISTINCT TOLOWER(res.name)) AS resNames WHERE // 直接翻译需求逻辑:排除两种不符合的情况 NOT ( (ANY(name IN providerNames WHERE name = "adani transmission limited") AND ANY(name IN addressNames WHERE name = "formosa")) OR ANY(name IN resNames WHERE name = "video interview data") ) ORDER BY node.createdAt DESC RETURN DISTINCT node
逻辑说明:
- 用
OPTIONAL MATCH处理服务可能没有提供商、地址或依赖的场景,避免漏掉这类节点 - 收集相关名称并统一转小写,确保匹配不区分大小写
- 在
WHERE子句中直接实现需求的否定逻辑,清晰对应原始业务规则 - 最后按
createdAt排序并返回结果
内容的提问来源于stack exchange,提问作者Mittal Vaghela
相关产品推荐
相关产品推荐

