如何使用OR匹配节点标签?

问题描述 投票:0回答:2
match (p:Product {id:'5116003'})-[r]->(o:Attributes|ExtraAttribute) return p, o

如何在这样的查询中匹配两个可能的节点标签?

根据cybersam的建议,我改为以下内容:

MATCH (p:Product {id:'5116003'})-[r]->(o) 
WHERE o:Attributes OR o:ExtraAttributes
**WHERE any(key in keys(o) WHERE toLower(key) contains 'weight')** 
return o

现在我需要添加第二个'where'子句。如何修改?

neo4j cypher
2个回答
0
投票

这两种单标签形式的查询:

MATCH (p:Product {id:'5116003'})-->(o:Attributes) RETURN p, o;

MATCH (p:Product {id:'5116003'})-->(o) WHERE o:Attributes RETURN p, o;

产生相同的执行计划,如下(我假设在:Product(id)上有一个索引):

+-----------------+----------------+------+---------+------------------+--------------+
| Operator        | Estimated Rows | Rows | DB Hits | Variables        | Other        |
+-----------------+----------------+------+---------+------------------+--------------+
| +ProduceResults |              0 |    0 |       0 | o, p             | p, o         |
| |               +----------------+------+---------+------------------+--------------+
| +Filter         |              0 |    0 |       0 | anon[33], o, p   | o:Attributes |
| |               +----------------+------+---------+------------------+--------------+
| +Expand(All)    |              0 |    0 |       0 | anon[33], o -- p | (p)-->(o)    |
| |               +----------------+------+---------+------------------+--------------+
| +NodeIndexSeek  |              0 |    0 |       1 | p                | :Product(id) |
+-----------------+----------------+------+---------+------------------+--------------+

以上第二个查询的这种双标签形式:

MATCH (p:Product {id:'5116003'})-->(o) WHERE o:Attributes OR o: ExtraAttribute RETURN p, o;

生成一个非常相似的执行计划(因此可能不会更昂贵):

+-----------------+----------------+------+---------+------------------+-------------------------------------+
| Operator        | Estimated Rows | Rows | DB Hits | Variables        | Other                               |
+-----------------+----------------+------+---------+------------------+-------------------------------------+
| +ProduceResults |              0 |    0 |       0 | o, p             | p, o                                |
| |               +----------------+------+---------+------------------+-------------------------------------+
| +Filter         |              0 |    0 |       0 | anon[33], o, p   | Ors(o:Attributes, o:ExtraAttribute) |
| |               +----------------+------+---------+------------------+-------------------------------------+
| +Expand(All)    |              0 |    0 |       0 | anon[33], o -- p | (p)-->(o)                           |
| |               +----------------+------+---------+------------------+-------------------------------------+
| +NodeIndexSeek  |              0 |    0 |       1 | p                | :Product(id)                        |
+-----------------+----------------+------+---------+------------------+-------------------------------------+

顺便说一句,@ BrunoPeres在答案中的第一个查询也有类似的执行计划,但Filter操作是非常不同的。目前尚不清楚哪个更快。

[UPDATE]

要回答您更新的问题:由于您不能拥有2个背靠背的WHERE条款,您可以在现有的WHERE子句中添加更多术语,如下所示:

MATCH (p:Product {id:'5116003'})-[r]->(o)
WHERE
  (o:Attributes OR o:ExtraAttributes) AND
  ANY(key in KEYS(o) WHERE TOLOWER(key) CONTAINS 'weight')
RETURN o;

1
投票

您可以尝试使用any()函数:

match (p:Product {id:'5116003'})-[r]->(o)
where any (label in labels(o) where label in ['Attributes', 'ExtraAttribute'])
return p, o

此外,如果您有APOC procedures,您可以使用apoc.path.expand路径扩展器程序,该程序从遵循给定关系的起始节点扩展,从最小级别到最大级别,遵循标签过滤器。

match (p:Product {id:'5116003'})
call apoc.path.expand(p, null,"+Attributes|ExtraAttribute",0,1) yield path
with nodes(path) as nodes
// return p and o nodes
return nodes[0], nodes[1]

See more here

热门问题
推荐问题
最新问题