排序
概览
在本指南中,您可以了解如何使用排序操作通过 MongoDB Java 驱动程序对读取操作的结果进行排序。
排序操作按照您指定的排序条件对查询返回的文档进行 排序。排序标准是您传递给 MongoDB 的规则,用于描述您希望如何对数据进行排序。排序标准的一些示例是:
- 最小数到最大数
- 一天中的最早时间到一天中的最晚时间
- 按名字的字母顺序
如果您愿意,您应该阅读本指南:
- 执行升序排序和降序排序。
- 结合排序标准。
- 对文本搜索的文本分数进行排序 。
本指南中的示例使用包含以下文档的示例集合:
{"_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 文档 。
您可以使用实例的sort()
方法FindIterable
如下:
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
builder 类的更多信息,请参阅我们 的 Sorts builder 指南。
有关本节中的类和接口的更多信息,请参阅以下 API 文档:
排序方向
您的排序方向可以是升序或降序。升序排序将您的结果从小到大排序。降序排序您的结果从最大到最小。
以下是一些按升序排序的数据示例:
- 数字:1、2、3、43、43、55、120
- 日期:1990-03-10、1995-01-01、2005-10-30、2005-12-21
- 单词 (ASCII):香蕉、莳萝、胡萝卜、黄瓜、鹰嘴豆泥
以下是一些按降序排序的数据示例:
- 数字:100、30、12、12、9、3、1
- 日期:2020-01-01、1998-12-11、1998-12-10、1975-07-22
- 单词(反向 ASCII):梨、葡萄、苹果、奶酪
以下小节显示了如何指定这些排序条件。
升序
要指定升序排序,请使用Sorts.ascending()
静态工厂方法。将Sorts.ascending()
您需要按升序排序的字段的名称传递给方法。
您可以将sort()
方法的输出传递给方法Sorts.ascending()
以指定字段的升序,如下所示:
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"}
文本搜索
您可以通过集合的文本索引指定的每个结果字段的字符串值与搜索字符串的匹配程度来指定文本搜索结果的顺序 。文本搜索分配一个数字 文本分数来指示每个结果与搜索字符串的匹配程度。使用 Sorts.metaTextScore()
静态工厂方法来构建您的排序标准以按文本分数排序。
在下面的代码示例中,我们展示了如何使用该 Sorts.metaTextScore()
方法对样本集合的文本搜索结果进行排序。该代码示例使用Filters、 Indexes和 Projections构建器。该代码示例执行以下操作:
- 为字段 上的样本集合创建文本索引
food
。如果调用createIndex()
指定集合中已存在的索引,则该操作不会创建新索引。 - 运行您的文本搜索短语“枫糖甜甜圈”。
- 将文本分数作为
score
字段投影到您的查询结果中 。 - 按文本分数对结果进行排序(最佳匹配优先)。
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}
MongoDB 4.4 或更高版本的文本搜索结构已更改。您不再需要投影Projections.metaTextScore()
到您的 FindIterable
实例中以对文本分数进行排序。此外,您$meta
在排序中使用的文本分数聚合操作中指定的字段名称将被忽略。这意味着您传递给的字段名称参数将Sorts.metaTextScore()
被忽略。
官方文档:https://docs.mongodb.com/drivers/java/sync/current/fundamentals/crud/read-operations/sort/