使用 Mongo C# 驱动程序时,查询排序是在 Mongo 内还是在 C# 级别进行?

When using the Mongo C# driver, does query sorting occur within Mongo, or at the C# level?

假设您想要使用 C# 驱动程序从 Mongo 数据库中检索一堆具有时间戳字段的文档,并且您希望它们按时间戳降序排列 (-1)。

在创建索引时,对于按这种方式排序的查询,是否需要将时间戳字段包含在-1 顺序中?或者它是不必要的,因为只有在文档从 Mongodb 中提取并转换为 C# 对象后才会发生排序,因此由 .NET 排序 "in-memory"?

假设我的文档有以下字段: user_id, action_id, 和 时间戳

我想要一个索引来帮助搜索用户的所有操作,并按降序排列。我的索引应该只包含 user_id 和 action_id,还是应该也使用时间戳字段?

Accodring to the docs,Mongo 驱动程序包含针对 Mongo 聚合框架的 LINQ 实现。这意味着像

这样的查询
var query = from p in collection.AsQueryable()
            orderby p.Name, p.Age descending
            select p;

//or

var query = collection.AsQueryable()
    .OrderBy(p => p.Name)
    .ThenByDescending(p => p.Age);

将映射到以下聚合管道:

[
    { $sort: { Name: 1, Age: -1 } },
]

当然你不一定非要使用LINQ,你也可以不用它写等价的查询。但答案是肯定的,驱动程序确实支持将您的查询转换为在数据库端执行的内容。

This page in the docs 指的是我相信您所描述的确切情况:

db.records.createIndex( { a: 1 } )

同时支持顺序和逆序遍历:

db.records.find().sort( { a: 1 } )
db.records.find().sort( { a: -1 } )

文档中有大量关于索引的信息,因此我建议您仔细阅读它们,了解什么最适合您的用例。

MongoDB 能够在将数据发送回客户端之前对数据进行排序。当您在查询中提供 sort 子句时,实际执行排序的是 mongod,而不是驱动程序或 .NET 运行时。

对于排序,可能会发生两种情况,具体取决于可用的索引:

  1. 使用索引排序
  2. 不使用索引排序

一个好的经验法则是,如果您想对某个字段进行排序,为该查询创建的索引需要 end 该字段。

因此,如果您在 上查询 timestamp 字段,那么您只需要 timestamp: -1timestamp: 1 的索引。该索引可用于任一排序方向的查询。

如果您在多个字段上进行查询,那么您希望索引以 timestamp 结尾。因此,对于您提供的示例,您可能需要一个像 { user_id: 1, action_id: 1, timestamp: -1 } 这样的索引,它将支持该确切查询。

如果不存在可用于排序的索引,则会发生在内存中。但是,内存中的排序存在限制,以防止服务降级。在撰写本文时,it is 32 MB。如果排序操作需要更多,则需要创建索引。