FILTER

FILTER 用于向查询中添加过滤条件,类似于 Cypher® 的 WHERE。与 WHERE 不同,FILTER 不是子句,这意味着它可以独立于 MATCHOPTIONAL MATCHWITH 子句使用,但不能在它们内部使用。

示例图

以下图表用于下方的示例

要重建该图,请在空的 Neo4j 数据库中运行以下查询

CREATE (andy:Swedish:Person {name: 'Andy', age: 36}),
       (timothy:Person {name: 'Timothy', age: 38}),
       (peter:Person {name: 'Peter', age: 35}),
       (lisa:Person {name: 'Lisa', age: 48}),
       (john:Person {name: 'John', age: 40}),
       (susan:Person {name: 'Susan', age: 32}),
       (andy)-[:KNOWS {since: 2012}]->(timothy),
       (andy)-[:KNOWS {since: 1999}]->(peter),
       (peter)-[:KNOWS {since: 2005}]->(lisa),
       (lisa)-[:KNOWS {since: 2010}]->(john),
       (john)-[:KNOWS {since: 2021}]->(susan)

基本过滤

基于节点标签过滤
MATCH (n)
FILTER n:Swedish
RETURN n.name AS name
结果
名称 (name)

"Andy"

行:1

基于节点属性过滤
MATCH (n:Person)
FILTER n.age < 35
RETURN n.name AS name, n.age AS age
结果
名称 (name) age

“Susan”

32

行:1

基于关系属性过滤
MATCH (p:Person)-[r:KNOWS]->(n:Person)
FILTER r.since > 2010
RETURN p.name AS person,
       r.since AS knowsSince,
       n.name AS otherPerson
结果
person knowsSince otherPerson

"Andy"

2012

"Timothy"

"John"

2021

“Susan”

行:2

基于动态标签和类型过滤

若要使用动态计算的值来过滤标签或关系类型,请使用 $(<expr>),其中 <expr> 是任何 Cypher 表达式

参数
{
  "label": "Swedish"
}
基于动态计算的节点标签过滤
MATCH (n)
FILTER n:$($label)
RETURN labels(n) AS labels
结果
标签

["Person", "Swedish"]

行:1

基于动态属性过滤

若要使用动态计算的名称来过滤属性,请使用方括号 []

参数
{
  "propname": "age"
}
基于动态计算的节点属性过滤
MATCH (n:Person)
FILTER n[$propname] > 40
RETURN n.name AS name, n.age AS age
结果
名称 (name) age

“Lisa”

48

行:1

FILTERWHERE 的区别

FILTERWHERE 都用于向查询应用过滤。然而,由于 FILTER 是一个子句,而 WHERE 是一个子句(subclause,意指从属子句),两者之间存在一些重要区别。

  • FILTER 在实体被匹配之后起作用,而 WHERE 在匹配执行之前限制哪些行会被匹配。

  • FILTER 不能在 MATCHOPTIONAL MATCHWITH 子句中使用,只能与它们并列使用。这意味着,与 WHERE 不同,FILTER 不能用于在模式内部添加过滤条件。

示例 1. FILTERWHERE 的区别

OPTIONAL MATCH 示例强调了 WHERE 子句与 FILTER 子句之间的差异。

WHERE 约束 OPTIONAL MATCH 模式
UNWIND [32,37,40] AS ageValue
OPTIONAL MATCH (p:Person)
WHERE p.age = ageValue
RETURN p.name AS name, p.age AS age
结果
名称 (name) age

“Susan”

32

NULL

NULL

"John"

40

行:3

由于 WHERE 是属于 OPTIONAL MATCH 的从属子句,它仅过滤匹配项,但不影响返回的行数。在此例中,OPTIONAL MATCH 始终保留来自 UNWIND 的所有行,且 WHERE 不会移除任何返回 NULL 的行。如果将 WHERE 替换为 FILTER,情况则不同。

FILTEROPTIONAL MATCH 添加后过滤
UNWIND [32,37,40] AS ageValue
OPTIONAL MATCH (p:Person)
FILTER p.age = ageValue
RETURN p.name AS name, p.age AS age
结果
名称 (name) age

“Susan”

32

"John"

40

行:2

WHERE 不同,FILTER 不是 OPTIONAL MATCH 的一部分,因此会根据表达式中提供的条件从结果集中移除整行。即,当 OPTIONAL MATCH 未能找到匹配项且 pNULL 时,无法对 FILTER p.age = ageValue 进行求值,导致整行被移除。

示例 2. FILTER 不能在模式内部使用

由于 WHERE 是限定所描述模式的从属子句,因此它可以用在模式内部。

节点模式内的 WHERE
WITH 35 AS minAge
MATCH (a:Person WHERE a.name = 'Andy')-[:KNOWS]->(b:Person WHERE b.age > minAge)
RETURN b.name AS name
结果
名称 (name)

"Timothy"

行:1

对于 FILTER 来说并非如此,作为一个子句,它不能放置在模式中。

不允许 — 模式内部的 FILTER
WITH 35 AS minAge
MATCH (a:Person FILTER a.name = 'Andy')-[:KNOWS]->(b:Person FILTER b.age > minAge)
RETURN b.name AS name

有关如何在固定长度和可变长度模式匹配中使用 WHERE 的更多信息,请参阅 WHERE → 过滤模式

FILTER 作为 WITH * WHERE 的替代方案

与依赖 MATCHOPTIONAL MATCHWITH 来定义作用域的 WHERE 不同,FILTER 可以独立于这些子句过滤查询。这可以使某些查询更加简洁。

例如,以下两个查询是等效的

使用 WITH * WHERE 进行过滤
UNWIND [1, 2, 3, 4, 5, 6] AS x
WITH x
WHERE x > 2
RETURN x
使用 FILTER 进行过滤
UNWIND [1, 2, 3, 4, 5, 6] AS x
FILTER x > 2
RETURN x

因此,FILTER 可以被视为 Cypher 中 WITH * WHERE <predicate> 结构的替代方案。

示例 3. 在 LOAD CSV 中使用 FILTER 代替 WITH * WHERE

以下两个 LOAD CSV 命令是等效的

companies.csv
Id,Name,Location,Email,BusinessType
1,Neo4j,San Mateo,contact@neo4j.com,P
2,AAA,,info@aaa.com,
3,BBB,Chicago, info@ ,G
,CCC,Michigan,info@ccc.com,G
使用 WITH * WHERELOAD CSV
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
WITH row
WHERE row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})
使用 FILTERLOAD CSV
LOAD CSV WITH HEADERS FROM 'file:///companies.csv' AS row
FILTER row.Id IS NOT NULL
MERGE (c:Company {id: row.Id})

然而,尽管 FILTER 可以作为 WITH * WHERE <predicate> 结构的替代方案,但它不具备 WITH 对后续子句中的变量进行操作的能力。FILTER 也不能重命名(alias)或创建新变量。换句话说,FILTER 仅具备 WITH * WHERE <predicate> 的功能,而不具备 WITH <selectedVariable> AS <newVariableName> WHERE <predicate> 的功能。