我想进行搜索,并且想要从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。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
相比如何? - jjaderbergNeo4j 3.4.7中,当使用两个OR筛选器的WHERE查询时,查询规划器会对2个NodeByLabelScan进行UNION和DISTINCT操作。尝试在Offshore Leaks Database沙盒上执行EXPLAIN MATCH (o) WHERE o:Officer OR o:Entity RETURN o
查询,得到以下规划结果:
MATCH (n)
WHERE labels(n) in [['Male'],['Female']]
AND n.name =~ '.ail.'
RETURN n
['男','女']
? - Ooker对于v3.5,我们可以做以下事情:
MATCH (n) WHERE (n:User OR n:Admin) AND n.name CONTAINS "ail" RETURN n
╒══════════════════╕
│"n" │
╞══════════════════╡
│{"name":"Abigail"}│
├──────────────────┤
│{"name":"Bailee"} │
└──────────────────┘
如果你需要处理合并集或者避免使用UNION,另一个选项是:
MATCH(m:Male) WHERE m.name=~'.ail.' WITH COLLECT(m) AS male
MATCH(f:Female) WHERE f.name=~'.ail.' WITH male, COLLECT(f) AS female
UNWIND (male + female) AS person
RETURN person.name;
这种方法并不像使用 UNION 那样高效,但仍然避免了昂贵的 AllNodesScan 操作符。在我的用例中,查询已经包含了一个不同目的的 UNION。
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
- artemisian
(n)-[:rel1 | rel2]->(m)
,其中|
表示OR
。 - Lyman ZergaWHERE
子句就能工作的其他模式。欢迎在Neo4j github存储库提交功能请求。 - jjaderberg