MongoDB find()查询是否返回按创建时间排序的文档?

MongoDB find()查询是否返回按创建时间排序的文档?,mongodb,sorting,database,Mongodb,Sorting,Database,我需要按创建时间(从最早到最新)排序的文档 由于ObjectID默认保存时间戳,因此我们可以使用它通过CollectionName.find().sort({u id:1})按创建时间对文档进行排序 另外,我注意到常规的CollectionName.find()query总是以与CollectionName.find().sort({u id:1})相同的顺序返回文档 我的问题是: CollectionName.find()是否保证以与CollectionName.find().sort({u

我需要按创建时间(从最早到最新)排序的文档

由于ObjectID默认保存时间戳,因此我们可以使用它通过
CollectionName.find().sort({u id:1})
按创建时间对文档进行排序


另外,我注意到常规的
CollectionName.find()
query总是以与
CollectionName.find().sort({u id:1})
相同的顺序返回文档

我的问题是:

CollectionName.find()
是否保证以与
CollectionName.find().sort({u id:1})
相同的顺序返回文档,以便我可以不进行排序

CollectionName.find()是否保证以与CollectionName.find().sort({u id:1})相同的顺序返回文档

不,不是如果未指定任何顺序,则使用所谓的“自然”顺序。这意味着文档将按照它们在数据文件中实际出现的顺序返回

现在,如果您只插入文档而从不修改它们,那么这种自然顺序将与递增的
\u id
顺序一致。但是,想象一下,您以这样的方式更新文档,文档的大小会增加,并且必须移动到数据文件内部的空闲插槽中(通常这意味着文件末尾的某个位置)。如果您现在查询文档,它们将不会遵循任何合理的(外部观察者)顺序

所以,如果你关心秩序,就把它说清楚

资料来源:

自然秩序

数据库引用磁盘上文档的顺序。这是默认的排序顺序。请参阅$natural并按自然顺序返回

测试脚本(针对困惑的用户)
>db.foo.insert({name:'Joe'})
WriteResult({“n插入”:1})
>db.foo.insert({name:'Bob'})
WriteResult({“n插入”:1})
>db.foo.find()
{“_id”:ObjectId(“55814b944e019172b7d358a0”),“name”:“Joe”}
{“_id”:ObjectId(“55814ba44e019172b7d358a1”),“name”:“Bob”}
>db.foo.update({u id:ObjectId(“55814b944e019172b7d358a0”)},{$set:{答案:"在分片集合上,$natural运算符返回按自然顺序排序的集合扫描,即数据库在磁盘上插入和存储文档的顺序。包含按$natural顺序排序的查询不使用索引来实现查询谓词,但以下情况除外:如果查询谓词是_id字段上的相等条件{{u id:},则具有按$natural顺序排序的查询可以使用{u id索引。如果查询包含$text表达式,则不能指定$natural排序顺序。“})
WriteResult({“nMatched”:1,“nUpserted”:0,“nModified”:1})
>db.foo.find()
{“_id”:ObjectId(“55814ba44e019172b7d358a1”),“name”:“Bob”}
{“_id”:ObjectId(“55814b944e019172b7d358a0”),“姓名”:“乔”,“答案”:”在分片集合上,$natural运算符返回按自然顺序排序的集合扫描,即数据库在磁盘上插入和存储文档的顺序。包含按$natural顺序排序的查询不使用索引来实现查询谓词,但以下情况除外:如果查询谓词是_id字段上的相等条件{{u id:},则具有按$natural顺序排序的查询可以使用{u id索引。如果查询包含$text表达式,则不能指定$natural排序顺序。“}
不,不完全是这样。
db.collection.find()

结果排序

除非指定sort()方法或使用$near运算符,否则MongoDB不保证查询结果的顺序

只要您的数据文件相对较新,并且很少发生更新,文档就可能(而且大多数情况下都会)按
\u id
排序返回,因为ObjectId是单调递增的

在生命周期的后期,旧文档可能已从其旧位置移动(因为它们的大小增加,并且文档从未分区),而新文档则在以前被另一个文档占用的位置写入。在这种情况下,新文档可能会返回到两个旧文档之间的位置

\u id
对文档进行排序没有什么错,因为索引将用于排序,只会为文档检索增加一些延迟

但是,出于以下几个原因,我强烈建议不要将ObjectId用于日期操作:

  • ObjectId不能用于日期比较查询。因此,您无法查询在日期x和日期y之间创建的所有文档。若要存档,您必须加载所有文档,从ObjectId中提取日期并进行比较,这是非常低效的
  • 如果创建日期很重要,则应在文档中明确说明
  • 我将ObjectId视为最后一种方法,用于
    \u id
    字段,并且倾向于将其他值(有时使用复合)作为
    \u id
    s,因为该字段默认为索引,并且很可能通过使用更有意义的值作为id来保存宝贵的RAM
  • 您可以使用下面的示例,它利用

    并且使用

    db.collection.find().sort({_id.creationDate:1})
    

    “自然”顺序只能通过使用
    .sort({“$Natural”:1})
    来实现。这是请求数据“按存储在磁盘上的顺序”的唯一方法。此外,由于“磁盘上的数据”可以“移动”(并且经常移动),因此这不是“插入顺序”.仔细阅读,这个答案并不声称自然顺序与插入顺序相同。事实上,整个答案都是关于它如何不同。引用:“如果你没有指定任何顺序,那么就使用所谓的“自然”顺序”。你的话不是我的。那不是真的。是的,自然顺序,不是插入顺序。此测试无效。分片集合使用“分片键”进行选择,可能使用“分散-聚集”。因此主键不是
    {
      _id: {
        creationDate: new ISODate(),
        user: { 
          "$ref" : "creators",
          "$id" : "mwmahlberg",
          "$db" : "users"
        }
      }
    }
    
    db.collection.find().sort({_id.creationDate:1})