EXISTS 子查询

EXISTS 子查询可用于查找图中是否存在指定模式至少一次。它与路径模式的功能相同,但更强大,因为它允许您在内部使用 MATCHWHERE 子句。

示例图

以下图用于下方示例

subqueries graph

要重新创建该图,请在空的 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

"Andy"

"Peter"

行数: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

"Andy"

行数: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

"Peter"

行数:1

EXISTS 子查询在 WHERE 子句之外

EXISTS 子查询表达式可以出现在任何表达式有效的地方。这里的结果是一个布尔值,表示子查询是否能找到给定模式。

MATCH (person:Person)
RETURN person.name AS name, EXISTS {
  MATCH (person)-[:HAS_DOG]->(:Dog)
} AS hasDog
name hasDog

"Andy"

true

"Timothy"

false

"Peter"

true

行数:3

带有 UNIONEXISTS 子查询

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

"Andy"

true

"Timothy"

true

"Peter"

true

行数:3

带有 WITHEXISTS 子查询

即使使用 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 子句引入了一个新变量。请注意,主查询中引用的外部作用域变量 personWITH 子句之后仍然可用。

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

"Peter"

行数:1

带有 RETURNEXISTS 子查询

EXISTS 子查询不需要在子查询末尾有 RETURN 子句。如果存在,也不需要使用别名,这与CALL 子查询不同。在 EXISTS 子查询中返回的任何变量在子查询之后都将不可用。

MATCH (person:Person)
WHERE EXISTS {
    MATCH (person)-[:HAS_DOG]->(:Dog)
    RETURN person.name
}
RETURN person.name AS name
name

"Andy"

"Peter"

行数:2

规则

对于 EXISTS 子查询,以下情况成立

  • 允许任何非写入查询。

  • 如果 EXISTS 子查询评估为至少一行,则整个表达式将变为 true。这也意味着系统只需评估是否存在至少一行,并可以跳过其余的工作。

  • EXISTS 子查询与常规查询的不同之处在于,最终的 RETURN 子句可以省略,因为子查询中定义的任何变量在表达式外部都将不可用,即使使用了最终的 RETURN 子句。

  • EXISTS 仅包含模式和可选 WHERE 子句的情况下,子查询中可以省略 MATCH 关键字。

  • EXISTS 子查询可以出现在查询中任何表达式有效的地方。

  • 在外部作用域中定义的任何变量都可以在子查询自己的作用域内引用。

  • 在子查询内部引入的变量不属于外部作用域,因此无法从外部访问。

© . All rights reserved.