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
子查询
可以与 MATCH
结合使用 WHERE
子句。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 |
WHERE
子句外部的 EXISTS
子查询
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
子查询可以出现在查询中任何表达式有效的的位置。 -
在外部作用域定义的任何变量都可以在子查询的内部作用域中引用。
-
在子查询内部引入的变量不属于外部作用域,因此无法在外部访问。