Neo4j:匹配多个标签(2个或更多)

Posted

技术标签:

【中文标题】Neo4j:匹配多个标签(2个或更多)【英文标题】:Neo4j: Match multiple labels (2 or more) 【发布时间】:2013-11-29 00:07:10 【问题描述】:

我想做一个搜索,我想从 2 个标签(OR 条件)开始遍历。例如,我需要找出所有标签为“男性”或“女性”且其属性为 name =~ '.ail.' 的节点。

【问题讨论】:

【参考方案1】:

您可以将此条件放在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 提交功能请求。 @Lyman Zerga 我也在很多地方搜索过,但没有类似的地方 我刚刚遇到了同样的问题,并使用 MATCH n WHERE n:Label1 OR n:Label2 方法解决了它。根据为我的查询运行 EXPLAIN 和 PROFILE 返回的内容,看起来AllNodesScan 没有被执行。在我的例子中,我有两个标签,有两个节点扫描,结果是联合的。所以,看起来第一个解决方案现在可能是最好的解决方案了。 有人可以确认@augustearth 的声明吗?我是neo4j新手,不知道怎么统计扫描次数和判断性能差异【参考方案2】:
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) 

【讨论】:

为什么每一步都需要“distinct”? 感谢您指出AllNodesScan,我认为现在已经解决了。我已经更新了我的答案,您对我使用UNION 的更详细的替代方案以及它与您的OPTIONAL MATCH/collect()/UNWIND 相比有何想法? 注意:UNION 不方便(在某些情况下不可用),因为目前(2.2)您无法对 UNION 的结果进行任何处理。例如,您不能使用 SKIP/LIMIT 或 COUNT。【参考方案3】:

在 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 会产生以下规划:

【讨论】:

【参考方案4】:

如果你想通过带有 OR 或 IN 条件的多个标签过滤节点,请使用以下代码:

MATCH (n)
WHERE labels(n) in [['Male'],['Female']]
AND n.name =~ '.ail.'
RETURN n

【讨论】:

这可行,但它使 AllNodesScan 性能不佳 为什么要使用嵌套列表?为什么不只是['Male','Female']【参考方案5】:

至于 v3.5,我们可以这样做:

MATCH (n) WHERE (n:User OR n:Admin) AND n.name CONTAINS "ail" RETURN n

得到:

╒══════════════════╕
│"n"               │
╞══════════════════╡
│"name":"Abigail"│
├──────────────────┤
│"name":"Bailee" │
└──────────────────┘

【讨论】:

【参考方案6】:

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 仅供参考。源 URL 发生了一些变化。这是新的:neo4j.com/docs/developer-manual/current/cypher/syntax/patterns/… 其实这是错误的,(a:User:Admin) 这个查询描述了一个节点什么时候是“User and also Admin” No a user OR Admin.

以上是关于Neo4j:匹配多个标签(2个或更多)的主要内容,如果未能解决你的问题,请参考以下文章

Neo4j中使用Louvain算法和标签传播算法(LPA)对漫威英雄进行社群分析

将 iOS 中的 UIlabel 文本字段限制为两个字符,输入 3 个或更多时重置

正则表达式:匹配模式后跟一个空格但不匹配2个或更多空格或EOF

正则表达式匹配超过 2 个空格但不匹配新行

django url如何指定2个或更多字符串

Neo4j:标签与索引属性?