【发布时间】:2013-11-29 00:07:10
【问题描述】:
我想做一个搜索,我想从 2 个标签(OR 条件)开始遍历。例如,我需要找出所有标签为“男性”或“女性”且其属性为 name =~ '.ail.' 的节点。
【问题讨论】:
我想做一个搜索,我想从 2 个标签(OR 条件)开始遍历。例如,我需要找出所有标签为“男性”或“女性”且其属性为 name =~ '.ail.' 的节点。
【问题讨论】:
您可以将此条件放在WHERE 子句中:
MATCH (n)
WHERE n:Male OR n:Female
RETURN n
编辑
正如@tbaum 指出的那样,这执行AllNodesScan。当标签相当新时,我写了答案,并期望查询规划器最终为每个标签使用NodeByLabelScan 来实现它,就像它对单个标签的情况一样
MATCH (n)
WHERE n:Male
RETURN n
我仍然认为这是查询的合理表达,并且期望查询规划器使用标签扫描来实现它是合理的,但是从 Neo4j 2.2.3 开始,查询仍然使用 AllNodesScan 和标签过滤器。因此,这是一个更详细的替代方案。由于标签析取表示一个集合并集,并且这个并集可以用不同的方式表示,我们可以用查询计划器实现的方式来表示它,而无需扫描所有节点,而是以每个标签的 NodeByLabelScan 开头。
MATCH (n:Male)
WHERE n.name =~ '.ail.'
RETURN n
UNION MATCH (n:Female)
WHERE n.name =~ '.ail.'
RETURN n
这意味着为每个标签表达一次查询,并使用明确的UNION 将它们连接起来。这并不是不合理的,至少对于较少数量的标签来说,但我不清楚为什么查询计划者不能从更简单的查询中推断出相同的实现,所以我打开了一个 github 问题here。
【讨论】:
( n )-[: rel1 | rel2 ]->(m) 其中 ` | ` 表示OR
WHERE 子句的情况下工作的模式。随时通过 Neo4j github repository 提交功能请求。
AllNodesScan 没有被执行。在我的例子中,我有两个标签,有两个节点扫描,结果是联合的。所以,看起来第一个解决方案现在可能是最好的解决方案了。
MATCH n WHERE n:Label1 OR n:Label2
... 将导致 AllNodesScan 这是一个坏主意!
也许是一个更好的解决方案:
OPTIONAL MATCH (n1:Label1)
WITH collect(distinct n1) as c1
OPTIONAL MATCH (n2:Label2)
WITH collect(distinct n2) + c1 as c2
OPTIONAL MATCH (n3:Label3)
WITH collect(distinct n3) + c2 as c3
UNWIND c3 as nodes
RETURN count(nodes),labels(nodes)
【讨论】:
AllNodesScan,我认为现在已经解决了。我已经更新了我的答案,您对我使用UNION 的更详细的替代方案以及它与您的OPTIONAL MATCH/collect()/UNWIND 相比有何想法?
在 Neo4j 3.4.7 中,查询规划器执行一个 UNION,然后当您将一个带有 2 个 OR'ed 标签过滤器的 WHERE 查询交给它时,它执行一个 UNION 和 DISTINCT 2 NodeByLabelScans。尝试使用 sandbox Offshore Leaks Database 和 EXPLAIN MATCH (o) WHERE o:Officer OR o:Entity RETURN o 会产生以下规划:
【讨论】:
如果你想通过带有 OR 或 IN 条件的多个标签过滤节点,请使用以下代码:
MATCH (n)
WHERE labels(n) in [['Male'],['Female']]
AND n.name =~ '.ail.'
RETURN n
【讨论】:
['Male','Female']?
至于 v3.5,我们可以这样做:
MATCH (n) WHERE (n:User OR n:Admin) AND n.name CONTAINS "ail" RETURN n
得到:
╒══════════════════╕
│"n" │
╞══════════════════╡
│{"name":"Abigail"}│
├──────────────────┤
│{"name":"Bailee"} │
└──────────────────┘
【讨论】:
v3.0 的文档是这样说的:
也可以描述具有多个标签的节点:
(a:User:Admin)-->(b)
来源:https://neo4j.com/docs/developer-manual/current/cypher/#_labels
【讨论】:
MATCH (a:User:Admin)-[r]->(b) return a,r,b