如何使用MongoDB高效地分页批量结果

时间:2015-07-28 11:56:15

标签: mongodb mongodb-query

我在MongoDB集合上使用以下查询,这需要一个多小时才能完成。

db.collection.find({language:"hi"}).sort({_id:-1}).skip(5000).limit(1)

我试图以5000的批次结果获得结果以升序或降序处理文件" hi"作为语言领域的价值。所以我使用这个查询,我每次都通过递增"跳过"来跳过处理过的文档。值。

此系列中的文件数量刚刚超过2000万。 该字段的索引"语言"已经创建了。 我正在使用的MongoDB版本是2.6.7

此查询是否有更合适的索引可以更快地获得结果?

2 个答案:

答案 0 :(得分:3)

如果要对降序进行排序,则应创建一个多字段索引,该索引使用您排序的字段作为降序字段。您可以将这些字段设置为-1

此索引应该会大大提高您的排序性能:

db.collection.ensureIndex({ language: 1, _id: -1 });

如果您还想加快其他情况 - 检索按升序排序 - 创建第二个索引,如下所示:

db.collection.ensureIndex({ language: 1, _id: 1 });

请记住,当您不对结果进行排序时,您会按自然顺序接收它们。自然顺序通常是 插入顺序,但不能保证。有各种事件可能导致自然顺序混乱,因此当您关心订单时,您应该始终明确排序。此规则的唯一例外是capped collections,它始终保持插入顺序。

答案 1 :(得分:0)

为了以您想要的方式有效地“浏览”结果,最好使用“范围查询”并保留您处理的最后一个值。

你想要的“排序键”这里是_id,这样可以简化:

首先,您希望索引的顺序正确,而.createIndex()不是弃用的方法:

db.collection.createIndex({ "language": 1, "_id": -1 })

然后你想从头开始做一些简单的处理:

var lastId = null;

var cursor = db.collection.find({language:"hi"});
cursor.sort({_id:-1}).limit(5000).forEach(funtion(doc) {
    // do something with your document. But always set the next line
    lastId = doc._id;
})

这是第一批。现在,当你继续下一个:

var cursor = db.collection.find({ "language":"hi", "_id": { "$lt": lastId });
cursor.sort({_id:-1}).limit(5000).forEach(funtion(doc) {
    // do something with your document. But always set the next line
    lastId = doc._id;
})

这样在进行选择时始终会考虑lastId值。您可以在每个批次之间存储它,并从最后一个批次继续。

这比使用.skip()处理效率要高得多,$lt无论索引如何“仍然”需要“跳过”集合中的所有数据直到跳过点。

在此使用package business; message Employee { required string first_name = 1; required string last_name = 2; required string email = 3; } message Company { required string name = 1; optional string url = 2; repeated Employee employee = 3; } 运算符“过滤”您已处理的所有结果,以便您可以更快地移动。

相关问题