排序结果
概述
在本指南中,您可以学习如何使用 排序 操作,通过 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文档。
以下是如何使用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
构建器类的更多信息,请参阅我们的关于Sorts构建器的指南.
有关本节中类和接口的更多信息,请参阅以下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()
方法对样本集合上的文本搜索结果进行排序。代码示例使用过滤器、索引和投影构建器。代码示例执行以下操作
为您的样本集合上的
food
字段创建文本索引。如果您调用createIndex()
指定一个已在集合上存在的索引,则该操作不会创建新的索引。对短语"maple donut"执行文本搜索。
将文本分数投影到查询结果中的
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或更高版本中的文本搜索行为
对于MongoDB 4.4或更高版本,文本搜索的结构已更改。您不再将Projections.metaTextScore()
投影到您的FindIterable
实例中以便按文本分数排序。此外,在排序中使用的$meta文本分数聚合操作中指定的字段名称被忽略。这意味着传递给Sorts.metaTextScore()
的字段名称参数被忽略。
有关本节中类别的更多信息,请参阅以下API文档
获取更多信息,请参阅 Sorts 类 API 文档。有关 $text 查询运算符和 $meta 聚合管道运算符的更多信息,请参阅服务器手册文档。