COLLECT 子查询
COLLECT
子查询表达式可用于使用给定子查询返回的行创建列表。
COLLECT
子查询与 COUNT
和 EXISTS
子查询的不同之处在于,最终的 RETURN
子句是必需的。RETURN
子句必须返回正好一列。
示例图
以下图用于下面的示例
要重新创建图,请针对空 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'})
简单的 COLLECT
子查询
外部作用域引入的变量可以在 COLLECT
子查询中使用,无需导入。在这方面,COLLECT
子查询不同于 CALL
子查询,后者需要导入。以下查询对此进行了说明,并输出了名为 Ozzy
的狗的所有者
MATCH (person:Person)
WHERE 'Ozzy' IN COLLECT { MATCH (person)-[:HAS_DOG]->(dog:Dog) RETURN dog.name }
RETURN person.name AS name
name |
---|
|
行数:1 |
带有 WHERE
子句的 COLLECT
子查询
可以在 COLLECT
子查询中使用 WHERE
子句。MATCH
子句和外部作用域引入的变量可以在内部作用域中使用。
MATCH (person:Person)
RETURN person.name as name, COLLECT {
MATCH (person)-[r:HAS_DOG]->(dog:Dog)
WHERE r.since > 2017
RETURN dog.name
} as youngDogs
name | youngDogs |
---|---|
|
|
|
|
|
|
行数:3 |
带有 UNION
的 COLLECT
子查询
COLLECT
可与 UNION
子句一起使用。以下示例使用 UNION
子句显示每个人拥有的宠物名称的集合
MATCH (person:Person)
RETURN
person.name AS name,
COLLECT {
MATCH (person)-[:HAS_DOG]->(dog:Dog)
RETURN dog.name AS petName
UNION
MATCH (person)-[:HAS_CAT]->(cat:Cat)
RETURN cat.name AS petName
} AS petNames
name | petNames |
---|---|
|
|
|
|
|
|
行数:3 |
带有 WITH
的 COLLECT
子查询
外部作用域的变量对整个子查询可见,即使使用 WITH
子句也是如此。为避免混淆,不允许对这些变量进行遮蔽。当在内部作用域中定义了一个新引入的变量,其标识符与外部作用域变量相同,则会遮蔽外部作用域变量。在以下示例中,外部变量 name
被遮蔽,因此会抛出错误。
WITH 'Peter' as name
MATCH (person:Person {name: name})
RETURN COLLECT {
WITH 'Ozzy' AS name
MATCH (person)-[r:HAS_DOG]->(d:Dog {name: name})
RETURN d.name
} as dogsOfTheYear
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: 92))
可以在子查询中引入新变量,只要它们使用不同的标识符即可。在以下示例中,WITH
子句引入了一个新变量。请注意,主查询中引用的外部作用域变量 person
在 WITH
子句之后仍然可用。
MATCH (person:Person)
RETURN person.name AS name, COLLECT {
WITH 2018 AS yearOfTheDog
MATCH (person)-[r:HAS_DOG]->(d:Dog)
WHERE r.since = yearOfTheDog
RETURN d.name
} as dogsOfTheYear
name | dogsOfTheYear |
---|---|
|
|
|
|
|
|
行数:3 |
在其他子句中使用 COLLECT
子查询
COLLECT
可在查询中的任何位置使用,除了管理命令,在管理命令中,COLLECT
表达式受到限制。以下是一些示例,说明 COLLECT
如何在查询的不同位置使用
在 RETURN
中使用 COLLECT
MATCH (person:Person)
RETURN person.name,
COLLECT {
MATCH (person)-[:HAS_DOG]->(d:Dog)
MATCH (d)-[:HAS_TOY]->(t:Toy)
RETURN t.name
} as toyNames
person.name | toyNames |
---|---|
|
|
|
|
|
|
行数:3 |
在 SET
中使用 COLLECT
MATCH (person:Person) WHERE person.name = "Peter"
SET person.dogNames = COLLECT { MATCH (person)-[:HAS_DOG]->(d:Dog) RETURN d.name }
RETURN person.dogNames as dogNames
dogNames |
---|
|
行数:1 |
使用 COLLECT
与 collect()
COLLECT
处理 null
值的方式与聚合函数 collect()
不同。collect()
函数会自动删除 null
值。COLLECT
不会自动删除 null
值。但是,可以通过在子查询中添加过滤步骤来删除它们。
以下查询说明了这些差异
MATCH (p:Person)
RETURN collect(p.nickname) AS names
names |
---|
|
行数:1 |
RETURN COLLECT {
MATCH (p:Person)
RETURN p.nickname ORDER BY p.nickname
} AS names
names |
---|
|
行数:1 |
RETURN COLLECT {
MATCH (p:Person)
WHERE p.nickname IS NOT NULL
RETURN p.nickname ORDER BY p.nickname
} AS names
name |
---|
|
行数:1 |