EXISTS 子查询
EXISTS
子查询可用于查找图中是否存在指定模式至少一次。它与路径模式的功能相同,但更强大,因为它允许您在内部使用 MATCH
和 WHERE
子句。
示例图
以下图用于下方示例
要重新创建该图,请在空的 Neo4j 数据库上运行以下查询
CREATE
(andy:Swedish:Person {name: 'Andy', age: 36}),
(timothy:Person {name: 'Timothy', nickname: 'Tim', age: 25}),
(peter:Person {name: 'Peter', nickname: 'Pete', age: 35}),
(andy)-[:HAS_DOG {since: 2016}]->(:Dog {name:'Andy'}),
(timothy)-[:HAS_CAT {since: 2019}]->(:Cat {name:'Mittens'}),
(fido:Dog {name:'Fido'})<-[:HAS_DOG {since: 2010}]-(peter)-[:HAS_DOG {since: 2018}]->(:Dog {name:'Ozzy'}),
(fido)-[:HAS_TOY]->(:Toy{name:'Banana'})
简单 EXISTS
子查询
外部作用域引入的变量可以在 EXISTS
子查询中直接使用,无需导入。在这方面,EXISTS
子查询与 CALL
子查询不同,后者确实需要导入。以下示例展示了这一点
MATCH (person:Person)
WHERE EXISTS {
(person)-[:HAS_DOG]->(:Dog)
}
RETURN person.name AS name
name |
---|
|
|
行数:2 |
带有 WHERE
子句的 EXISTS
子查询
WHERE
子句可以与 MATCH
结合使用。MATCH
子句和外部作用域引入的变量可以在此作用域中使用。
MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
WHERE person.name = dog.name
}
RETURN person.name AS name
name |
---|
|
行数:1 |
嵌套 EXISTS
子查询
EXISTS
子查询可以像以下示例所示那样嵌套。嵌套也会影响作用域。这意味着可以从子查询内部访问所有变量,这些变量要么来自外部作用域,要么在同一个子查询中定义。
MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
WHERE EXISTS {
MATCH (dog)-[:HAS_TOY]->(toy:Toy)
WHERE toy.name = 'Banana'
}
}
RETURN person.name AS name
name |
---|
|
行数:1 |
EXISTS
子查询在 WHERE
子句之外
EXISTS
子查询表达式可以出现在任何表达式有效的地方。这里的结果是一个布尔值,表示子查询是否能找到给定模式。
MATCH (person:Person)
RETURN person.name AS name, EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
} AS hasDog
name | hasDog |
---|---|
|
|
|
|
|
|
行数:3 |
带有 UNION
的 EXISTS
子查询
Exists
可以与 UNION
子句一起使用,并且不需要 RETURN
子句。值得注意的是,如果一个分支有 RETURN
子句,那么所有分支都需要一个。下面的示例演示了如果其中一个 UNION
分支返回至少一行,整个 EXISTS
表达式将评估为 true。
MATCH (person:Person)
RETURN
person.name AS name,
EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
UNION
MATCH (person)-[:HAS_CAT]->(:Cat)
} AS hasPet
name | hasPet |
---|---|
|
|
|
|
|
|
行数:3 |
带有 WITH
的 EXISTS
子查询
即使使用 WITH
子句,外部作用域的变量在整个子查询中仍然可见。为避免混淆,不允许这些变量的影子化。当内部作用域中定义的新变量与外部变量同名时,就会发生影子化。在下面的示例中,外部变量 name
被影子化,因此将抛出错误。
WITH 'Peter' as name
MATCH (person:Person {name: name})
WHERE EXISTS {
WITH "Ozzy" AS name
MATCH (person)-[:HAS_DOG]->(d:Dog)
WHERE d.name = name
}
RETURN person.name AS name
The variable `name` is shadowing a variable with the same name from the outer scope and needs to be renamed (line 4, column 20 (offset: 90))
新变量可以引入到子查询中,只要它们使用不同的标识符。在下面的示例中,WITH
子句引入了一个新变量。请注意,主查询中引用的外部作用域变量 person
在 WITH
子句之后仍然可用。
MATCH (person:Person)
WHERE EXISTS {
WITH "Ozzy" AS dogName
MATCH (person)-[:HAS_DOG]->(d:Dog)
WHERE d.name = dogName
}
RETURN person.name AS name
name |
---|
|
行数:1 |
带有 RETURN
的 EXISTS
子查询
EXISTS
子查询不需要在子查询末尾有 RETURN
子句。如果存在,也不需要使用别名,这与CALL
子查询不同。在 EXISTS
子查询中返回的任何变量在子查询之后都将不可用。
MATCH (person:Person)
WHERE EXISTS {
MATCH (person)-[:HAS_DOG]->(:Dog)
RETURN person.name
}
RETURN person.name AS name
name |
---|
|
|
行数:2 |
规则
对于 EXISTS
子查询,以下情况成立
-
允许任何非写入查询。
-
如果
EXISTS
子查询评估为至少一行,则整个表达式将变为true
。这也意味着系统只需评估是否存在至少一行,并可以跳过其余的工作。 -
EXISTS
子查询与常规查询的不同之处在于,最终的RETURN
子句可以省略,因为子查询中定义的任何变量在表达式外部都将不可用,即使使用了最终的RETURN
子句。 -
在
EXISTS
仅包含模式和可选WHERE
子句的情况下,子查询中可以省略MATCH
关键字。 -
EXISTS
子查询可以出现在查询中任何表达式有效的地方。 -
在外部作用域中定义的任何变量都可以在子查询自己的作用域内引用。
-
在子查询内部引入的变量不属于外部作用域,因此无法从外部访问。