ORDER BY

ORDER BY 指定子句输出的排序方式。它可以用作 RETURNWITH 之后的子句。从 Neo4j 5.24 开始,它也可以用作独立子句,单独使用或与 SKIP/OFFSETLIMIT 结合使用。

ORDER BY 依靠比较来排序输出,请参阅 值的排序和比较。您可以根据许多不同的值进行排序,例如节点/关系属性、节点/关系 ID 或大多数表达式。

除非使用 ORDER BY,否则 Neo4j 不会保证查询结果的行顺序。

示例图

以下图用于下面的示例

graph order by clause

要重新创建它,请针对空 Neo4j 数据库运行以下查询

CREATE
  (andy: Person {name: 'Andy', age: 34, length: 170}),
  (bernard: Person {name: 'Bernard', age: 36}),
  (charlotte: Person {name: 'Charlotte', age: 32, length: 185}),
  (andy)-[:KNOWS]->(bernard),
  (bernard)-[:KNOWS]->(charlotte)

按属性对节点排序

ORDER BY 用于对输出进行排序。

查询
MATCH (n)
RETURN n.name, n.age
ORDER BY n.name

返回节点,按其名称排序。

表 1. 结果
n.name n.age

"Andy"

34

"Bernard"

36

"Charlotte"

32

行数:3

按多个属性对节点排序

您可以通过在 ORDER BY 子句中声明每个变量来按多个属性排序。Cypher® 将根据列出的第一个变量对结果进行排序,对于相等的值,将转到 ORDER BY 子句中的下一个属性,依此类推。

查询
MATCH (n)
RETURN n.name, n.age
ORDER BY n.age, n.name

这将返回节点,首先按其年龄排序,然后按其名称排序。

表 2. 结果
n.name n.age

"Charlotte"

32

"Andy"

34

"Bernard"

36

行数:3

按 ID 对节点排序

ORDER BY 用于对输出进行排序。

查询
MATCH (n)
RETURN n.name, n.age
ORDER BY elementId(n)

返回节点,按其内部 ID 排序。

表 3. 结果
n.name n.age

"Andy"

34

"Bernard"

36

"Charlotte"

32

行数:3

当节点和关系被删除时,Neo4j 会重用其内部 ID。因此,依赖于 Neo4j 内部 ID 的应用程序很脆弱且可能不准确。建议改用应用程序生成的 ID。

按表达式对节点排序

ORDER BY 用于对输出进行排序。

查询
MATCH (n)
RETURN n.name, n.age, n.length
ORDER BY keys(n)

返回节点,按其属性排序。

表 4. 结果
n.name n.age n.length

"Bernard"

36

<null>

"Andy"

34

170

"Charlotte"

32

185

行数:3

按降序对节点排序

通过在要排序的变量之后添加 DESC[ENDING],排序将按相反顺序进行。

查询
MATCH (n)
RETURN n.name, n.age
ORDER BY n.name DESC

此示例返回节点,按其名称反向排序。

表 5. 结果
n.name n.age

"Charlotte"

32

"Bernard"

36

"Andy"

34

行数:3

排序 null

在排序结果集时,null 始终会出现在升序排序结果集的末尾,在降序排序时则出现在开头。

查询
MATCH (n)
RETURN n.length, n.name, n.age
ORDER BY n.length

返回按长度属性排序的节点,其中没有该属性的节点位于最后。

表 6. 结果
n.length n.name n.age

170

"Andy"

34

185

"Charlotte"

32

<null>

"Bernard"

36

行数:3

WITH 子句中排序

WITH 子句中存在 ORDER BY 时,紧随其后的子句将以指定的顺序接收记录。在以下子句之后,不保证保留顺序,除非该子句也具有 ORDER BY 子句。排序保证可以通过依赖于它们使用值的顺序的操作来利用。例如,这可以用于控制由 collect() 聚合函数生成的列表中项目的顺序。MERGESET 子句也具有可以通过这种方式控制的排序依赖关系。

查询
MATCH (n)
WITH n ORDER BY n.age
RETURN collect(n.name) AS names

collect 聚合函数构建的名称列表包含按 age 属性排序的名称。

表 7. 结果
names

["Charlotte","Andy","Bernard"]

行数:1

排序聚合或 DISTINCT 结果

在变量范围方面,ORDER BY 遵循特殊规则,具体取决于投影的 RETURNWITH 子句是聚合还是 DISTINCT。如果它是聚合或 DISTINCT 投影,则仅投影中可用的变量可用。如果投影不改变输出基数(聚合和 DISTINCT 所做的),则投影子句之前的变量也可使用。当投影子句隐藏已存在的变量时,只有新变量可用。

如果聚合表达式未在投影子句中列出,则也不允许在 ORDER BY 子句中使用它们。此规则是为了确保 ORDER BY 不会更改结果,而只会更改它们的顺序。

ORDER BY 和索引

在节点属性上使用 ORDER BY 的 Cypher 查询的性能可能会受到用于查找节点的索引的存在和使用情况的影响。如果索引可以按查询中请求的顺序提供节点,则 Cypher 可以避免使用代价高昂的 Sort 操作。有关此功能的更多信息,请参阅 基于范围索引的 ORDER BY

ORDER BY 用作独立子句

ORDER BY 可以作为独立子句使用,也可以与 SKIP/OFFSETLIMIT 结合使用。

ORDER BY 的独立使用
MATCH (n)
ORDER BY n.name
RETURN collect(n.name) AS names
表 8. 结果
names

["Andy", "Bernard", "Charlotte"]

行数:1

以下查询按 name 降序排列所有节点,跳过第一行并将结果限制为一行。

ORDER BYSKIPLIMIT 结合使用
MATCH (n)
ORDER BY n.name DESC
SKIP 1
LIMIT 1
RETURN n.name AS name
表 9. 结果
name

"Bernard"

行数:1