Docs 菜单
Docs 主页
/ / /
Java (Sync) 驱动程序
/ / /

对结果进行排序

在此页面上

  • Overview
  • 排序方法
  • 排序方向
  • 升序
  • 降序
  • 处理秩
  • 组合排序标准
  • 文本搜索(Text Search)

在本指南中,您可以了解如何使用排序操作对 MongoDB Java 驱动程序的读取操作结果进行排序。

排序操作按指定的排序条件对查询返回的文档进行排序。 排序条件是您传递给 MongoDB 的规则,描述您希望如何对数据进行排序。 排序条件的一些示例如下:

  • 最小数字到最大数字

  • 一天中的最早时间到一天中的最晚时间

  • 按名字字母顺序排列

如果您想执行以下操作,请阅读本指南:

  • 执行升序排序和降序排序。

  • 组合排序条件。

  • 根据 文本Atlas Search的文本分数进行排序。

本指南中的示例使用包含以下文档的样本集合:

{"_id": 1, "letter": "c", "food": "coffee with milk"}
{"_id": 3, "letter": "a", "food": "maple syrup"}
{"_id": 4, "letter": "b", "food": "coffee with sugar"}
{"_id": 5, "letter": "a", "food": "milk and cookies"}
{"_id": 2, "letter": "a", "food": "donuts and coffee"}
{"_id": 6, "letter": "c", "food": "maple donut"}

您可以对查询检索的结果进行排序,也可以在聚合管道内对结果进行排序。要对查询结果进行排序,请使用sort() 实例的FindIterable 方法。要对聚合管道中的结果进行排序,请使用Aggregates.sort() 静态工厂方法。这两个方法都接收实现Bson 接口的对象作为参数。有关更多信息,请参阅BSON接口的API文档。

您可以使用FindIterable实例的sort()方法,如下所示:

import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
collection.find().sort(ascending("_id"));

您可以在聚合管道中使用Aggregates.sort()方法,如下所示:

import com.mongodb.client.model.Aggregates;
import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
collection.aggregate(Arrays.asList(Aggregates.sort(ascending("_id"))));

前面的代码片段按_id字段的最小值到最大值对样本集合中的文档进行排序:

{"_id": 1, "letter": "c", "food": "coffee with milk"}
{"_id": 2, "letter": "a", "food": "donuts and coffee"}
{"_id": 3, "letter": "a", "food": "maple syrup"}
...

在前面的代码片段中,我们使用Sorts构建器类指定排序条件。 虽然可以使用任何实现Bson接口的类指定排序条件,但我们建议您通过Sorts构建器指定排序条件。 有关Sorts构建器类的更多信息,请参阅有关排序构建指南指南。

有关此部分中的类和接口的更多信息,请参阅以下 API 文档:

排序方向可以是升序,也可以是降序。 升序排序可将结果从小到大进行排序。 降序排序将结果按从大到小的顺序排列。

以下是按升序排序的数据的一些示例:

  • 数字:1、2、3、43、43、55、120

  • 日期:1990-03-10、1995-01-01、2005-10-30、2005-12-21

  • 单词 (ASCII):Banana,Dill,carrot,cucumber,hummus

以下是按降序排序的数据的一些示例:

  • 数字:100、30、12、12、9、3、1

  • 日期:2020 年 1 月 1 日、1998 年 12 月 11 日、1998 年 12 月 10 日、1975 年 7 月 22 日

  • 单词(反向 ASCII):pear、graves、apple、Cheese

以下各小节介绍如何指定这些排序条件。

要指定升序排序,请使用Sorts.ascending()静态工厂方法。 向Sorts.ascending()方法传递要升序排序的字段名称。

您可以将Sorts.ascending()方法的输出传递给sort()方法,以指定对字段进行升序排序,如下所示:

import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
collection.find().sort(ascending("<field name>"));

前面的sort()方法返回一个FindIterable对象,该对象可以迭代集合中的文档,并按指定字段名称从小到大排序。

在以下代码示例中,我们使用ascending()方法按_id字段对样本集合进行排序:

import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
List<Document> results = new ArrayList<>();
collection.find().sort(ascending("_id")).into(results);
for (Document result : results) {
System.out.println(result.toJson());
}

上述代码的输出如下所示:

{"_id": 1, "letter": "c", "food": "coffee with milk"}
{"_id": 2, "letter": "a", "food": "donuts and coffee"}
{"_id": 3, "letter": "a", "food": "maple syrup"}
...

要指定降序排序,请使用Sorts.descending()静态工厂方法。 向Sorts.descending()方法传递要降序排序的字段的名称。

以下代码片段展示了如何指定对_id字段进行降序排序:

import static com.mongodb.client.model.Sorts.descending;
// <MongoCollection setup code here>
collection.find().sort(descending("_id"));

前面的代码片段按降序返回样本集合中的文档:

{"_id": 6, "letter": "c", "food": "maple donut"}
{"_id": 5, "letter": "a", "food": "milk and cookies"}
{"_id": 4, "letter": "b", "food": "coffee with sugar"}
...

当两个或多个文档在用于对结果进行排序的字段中具有相同的值时,就会出现“并列”情况。 MongoDB 不保证出现并列时的排序顺序。 例如,假设我们使用以下代码对样本集合进行排序时遇到平局:

import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
collection.find().sort(ascending("letter"));

由于与查询匹配的多个文档都包含我们执行排序的字段的值“a”,因此可以按任意顺序返回以下文档:

{"_id": 3, "letter": "a", "food": "maple syrup"}
{"_id": 5, "letter": "a", "food": "milk and cookies"}
{"_id": 2, "letter": "a", "food": "donuts and coffee"}

如果必须保证具有相同值字段的文档具有特定的排序顺序,则可以指定其他字段,以在出现并列时作为排序依据。

我们可以指定对 letter 字段和 _id 字段进行升序排序,如下所示:

import static com.mongodb.client.model.Sorts.ascending;
// <MongoCollection setup code here>
collection.find().sort(ascending("letter", "_id"));

前面的代码片段按以下顺序返回样本集合中的文档:

{"_id": 2, "letter": "a", "food": "donuts and coffee"}
{"_id": 3, "letter": "a", "food": "maple syrup"}
{"_id": 5, "letter": "a", "food": "milk and cookies"}
{"_id": 4, "letter": "b", "food": "coffee with sugar"}
{"_id": 1, "letter": "c", "food": "coffee with milk"}
{"_id": 6, "letter": "c", "food": "maple donut"}

要组合排序条件,请使用Sorts.orderBy()静态工厂方法。 此方法可构造一个对象,其中包含排序条件的有序列表。 执行排序时,如果最左边的排序条件的结果为并列,则排序将使用列表中的下一个排序条件来确定顺序。

在以下代码片段中,我们使用orderBy()方法对数据进行排序,具体方法是对letter字段执行降序排序;如果出现平局,则对_id字段执行升序排序。

import static com.mongodb.client.model.Sorts.orderBy;
import static com.mongodb.client.model.Sorts.ascending;
import static com.mongodb.client.model.Sorts.descending;
// <MongoCollection setup code here>
Bson orderBySort = orderBy(descending("letter"), ascending("_id"));
collection.find().sort(orderBySort);

前面的代码片段按以下顺序返回样本集合中的文档:

{"_id": 1, "letter": "c", "food": "coffee with milk"}
{"_id": 6, "letter": "c", "food": "maple donut"}
{"_id": 4, "letter": "b", "food": "coffee with sugar"}
{"_id": 2, "letter": "a", "food": "donuts and coffee"}
{"_id": 3, "letter": "a", "food": "maple syrup"}
{"_id": 5, "letter": "a", "food": "milk and cookies"}

Atlas Searchstring您可以通过集合的文本索引指定的每个结果字段的 值与 的匹配程度来指定 文本Atlas Searchstring 结果的顺序。文本Atlas Search会分配一个数字文本分数,以指示每个结果与Atlas Search string的匹配程度。 使用Sorts.metaTextScore()静态工厂方法构建排序条件,按文本分数进行排序。

重要

确保创建文本索引

您需要在集合上建立文本索引才能执行文本Atlas Search 。 有关如何创建文本索引的更多信息,请参阅服务器手册文档。

在以下代码示例中,我们将向您展示如何使用Sorts.metaTextScore() 方法对Atlas Search 样本集合 上的文本 的结果进行排序。该代码示例使用FiltersIndexesProjections构建器。 该代码示例执行以下操作:

  1. food字段上为样本集合创建文本索引。 如果调用createIndex()时指定集合中已存在的索引,则该操作不会创建新索引。

  2. 在文本Atlas Search中运行短语“maple donut”。

  3. 将文本分数作为score字段投影到查询结果中。

  4. 按文本得分对结果进行排序(最匹配的排在前面)。

import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Indexes;
// <MongoCollection setup code here>
collection.createIndex(Indexes.text("food"));
Bson metaTextScoreSort = Sorts.metaTextScore("score");
Bson metaTextScoreProj = Projections.metaTextScore("score");
String searchTerm = "maple donut";
Bson searchQuery = Filters.text(searchTerm);
collection.find(searchQuery)
.projection(metaTextScoreProj)
.sort(metaTextScoreSort)
.into(results);
for (Document result : results) {
System.out.println(result.toJson());
}

上述代码的输出如下所示:

{"_id": 6, "letter": "c", "food": "maple donut", "score": 1.5}
{"_id": 2, "letter": "a", "food": "donuts and coffee", "score": 0.75}
{"_id": 3, "letter": "a", "food": "maple syrup", "score": 0.75}

注意

或更高版本中的文本Atlas Search 行为MongoDB4.4

MongoDB 4.4或更高版本的文本搜索结构已更改。 您不再将Projections.metaTextScore()项目到FindIterable实例中以对文本分数进行排序。 此外,在排序中使用的$meta文本分数聚合操作中指定的字段名称将被忽略。 这意味着您传递给Sorts.metaTextScore()的字段名称参数将被忽略。

有关本节中类的更多信息,请参阅以下 API 文档:

有关详细信息,请参阅 Sorts 类 API文档。有关$text查询运算符和$meta聚合管道操作符的更多信息,请参阅服务器手册文档。

后退

打开变更流