MongoDB查询结果的返回顺序

3
我有一个集合,其中有一个名为date的字段(也有索引)。它保存yyyymmdd的值(例如:201407312014073020140729等)。
基于日期,文档按降序存储。因此,集合中的第一个文档是20140731
当我使用带有过滤器{$gte : 20140720, $lte : 20140731}的查找命令时,mongodb返回按date字段升序排列的查询结果。
我知道可以使用sort,但如何使mongodb返回基于创建顺序的结果呢?
谢谢!

1
使用自然排序.sort( { $natural: 1 } ) - alecxe
@alexce 自然排序反映的是磁盘上的顺序,而不是插入顺序(特别是随着时间的推移),除非您将数据插入到一个有限制的集合中。另请参阅:当未指定排序顺序时Mongo按什么排序? - Stennie
1个回答

15

文档按照自然顺序存储

文档以日期为依据按降序存储,所以集合的第一个文档是20140731。

除非使用固定集合,否则在磁盘上(也称为自然顺序)无法保证文档的排序。

删除和移动文档(当文档超出其分配的记录空间时)会在空闲列表中创建可重用的空间。

以下是一个快速示例,可以在mongo shell中演示此过程:

// Start with an empty database & collection
use demodb; db.dropDatabase(); db.order.drop()

// Add some test data
for (i=0; i<1000; i++) {
    db.order.insert({'i': i})
}

// Looks like insertion order! (0..9)
db.order.find({}).limit(10);

// Pause 5s for effect :)
sleep(5000);

// Remove half the entries
db.order.remove({ i: { $lt: 500 }})

// Re-add the missing entries
for (i=0; i<500; i++) {
    db.order.insert({'i': i})
}

// Not the entries you expected .. space from deleted records was reused
db.order.find({}).limit(10)

// Clean up demodb
db.dropDatabase()

结果顺序

当我使用带有过滤器{$gte:20140720,$lte:20140731}的find命令时,mongodb会按“日期”字段以升序返回查询结果。

如果查询使用索引,文档将按照它们在索引中找到的顺序返回。在构建用于常见查询的索引时,您应该利用这一点(请参见:使用索引对查询结果进行排序)。

请注意,简单的索引(例如{date:1})可用于按升序或降序返回结果。

按ObjectID排序

如果您正在使用MongoDB的默认ObjectIDs作为_id,则可以按{ _id: 1 }排序来近似插入顺序,因为ObjectID的前4个字节包含时间戳。如果您想要使用此方法根据date和近似插入顺序对查询进行排序,则需要在{date:1,_id:1}上创建一个索引。

请注意,ObjectID通常由客户端驱动程序生成,因此如果应用服务器上存在时钟漂移(或在插入文档之前创建_id),则ObjectID可能不严格反映服务器看到的“插入顺序”。如果插入顺序的准确性非常重要,则通常可以在服务器端生成_id(方法因驱动程序而异)。


批量插入文档时如何维护顺序?例如,如果我一次插入5条记录并具有相同的时间戳。 - Akshay Naik
1
@AkshayNaik 磁盘上文档的顺序对于批量插入与单个插入没有区别。批量写操作可以被处理为有序无序,但这只决定了这些操作是串行还是并行执行。存储引擎管理磁盘上文档的顺序,对于默认的WiredTiger存储引擎以及旧版(现已弃用)的MMAPv1存储引擎,该顺序是未定义的。 - Stennie
在我的情况下,我有一个单一集合中超过数百万个文档。两天前我重新启动了服务器,所有集合中的文档顺序都被重新洗牌了,之前是按插入顺序排列的,现在的顺序是随机的。我正在寻找发生这种情况的原因。 - Akshay Naik
1
@AkshayNaik,使用WiredTiger时,内存中文档的表示与磁盘格式不同。如果您想要可预测的结果排序,则需要在唯一字段上指定排序顺序。 - Stennie
你是对的,添加一个sort({'_id':1})让我得到了原始顺序。 - Akshay Naik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接