当前位置: 首页 > 知识库问答 >
问题:

具有排序顺序的Mongo查询将以不正确的顺序返回文档

诸葛绍元
2023-03-14

我有一个mongo收藏,大约有60万份文档。我正在枚举集合,按_id排序。但是,文档不会按排序顺序返回。它们似乎是根据ObjectId的时间戳部分正确排序的,但不是根据pid字段。

这是我用来重现的c#代码

var cursor = m_collection.FindAll().SetSortOrder(SortBy.Ascending("_id"));

ObjectId previous = ObjectId.Empty;

foreach (var document in cursor)
{
    var id = document[IdField].AsObjectId;

    Throw.Assert(id > previous, "Sort order is invalid!");
    previous = id;
}

在某个时刻,断言被触发。我可以看到新的id具有与前一个相同的时间戳,但pid较低。

我本来以为使用{“_id”:1}进行排序将使用ObjectId的所有组件进行排序,而不仅仅是时间戳。

服务器对ObjectId使用的比较算法是否不同于C#客户端的ObjectId。比较?

共有1个答案

杜哲彦
2023-03-14

MongoDB C# CompareTo的源代码就在这里。该代码将< code>ObjectId的每个元素与3字节计数器进行比较。给定包含以下内容的ObjectId的性质:

    < li >一个4字节的值,表示自Unix纪元以来的秒数 < Li > 3字节的机器标识符 < li >一个2字节的进程id < li >和一个从随机值开始的3字节计数器

排序超出时间戳是没有意义的。<code>CompareTo</code>虽然准确,并将产生一致的结果,但排序方式可能不符合您的期望。

假设有两个对象是在相同的时间戳(4字节值)创建的,那么在C#中的< code>CompareTo的工作方式下,结果会有一些差异。因此,执行您所做的断言将导致一些混乱的结果,并且不应该被用作检测无序结果的方法。

大多数驱动程序在_id/ObjectId值不存在时创建它(包括C#驱动程序)。除了时间戳之外,您真的没什么可排序的。

你可以这样做:

Throw.Assert(id.Timestamp > previous.Timestamp, "Sort order is invalid!");
 类似资料:
  • 问题内容: 假设我有一个查询“ select * from子句,其中id在(0,2,5,1,3)中”,我实际上希望返回的行以它们在where子句中指定的相同顺序返回。ID的顺序将随查询的不同而改变,并且该顺序没有模式。 我知道可以更改数据模型,创建临时表等。但是请相信我,这些类型的解决方案在我的情况下将行不通。我也无法在应用程序代码中更改结果对象的顺序。 我还知道,不同的数据库引擎对事物的排序方式

  • 我使用Laravel查询生成器来获取一组行,按2列排序,然后(以前为)。然而,结果按(正确)对它们进行排序,但是(或)的次要顺序是不正确的。我是不是搞错了,是不是搞错了? 以下是我的问题: 这反过来又返回: 你看,14号票的顺序是71,75,72,而不是71,72,75。 以下是表格结构:

  • 问题内容: 是否可以以预定顺序进行声明,即 选择ID 7,2,5,9和8 并以该顺序返回它们 ,仅基于ID字段? 这两个语句以相同顺序返回它们: 问题答案: 我不认为这是可能的,但是在这里找到了一个博客条目,似乎可以满足您的需求: 将给不同的结果 返回给定第二个参数的位置,因此对于上面的第一种情况,7的位置在集合中的位置1,2的位置在2,依此类推-mysql在内部得出类似 然后按的结果排序。

  • 问题内容: 当我将以下Firebase数据库数据加载到tableView中时,数据按日期升序排序。如何通过降序排序(在顶部显示最新帖子)? 在Xcode中查询: JSON导出: 谢谢!! 编辑:下面的代码是整个解决方案,感谢Bawpotter 更新的查询: tableView cellForRowAtIndexPath Post.swift: 问题答案: 当Firebase将数据加载到tableV

  • 我有下表,其中包含PostID和到rootPostId的映射 我有以下疑问: 返回结果: 我希望返回以下内容,以便返回的第一个postId是传递到查询中的相应postId(postId=2),如下所示。 返回所需结果:

  • 问题内容: 我有这样的自定义订购需求: 我曾经想过用3个不同的选择查询的帮助下结合和。但是,我不能这样做,因为必须 在 和 之前 使用。 如何进行选择(或多个选择)以实现上面的自定义排序? 另一个解决方法可能会有所帮助,就是使此选择查询中返回的 第一条记录 成为最后一条记录,但是如何? 问题答案: 试试这个: 1亿个常量必须大于N。 这是一个简单的演示