2015-07-28 90 views
1

我正在使用以下查询来处理我的MongoDB集合,这需要花费一个多小时才能完成。如何使用MongoDB有效地分页结果批量处理

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

我试图让一个批次的5000结果以升序或降序排列的文档与“喜”在语言领域的价值的过程。所以我使用这个查询,其中我每次通过递增“跳过”值跳过处理的文档。

此集合中的文档数量仅略高于2000万。 已经创建了“语言”字段的索引。 我正在使用的MongoDB版本是2.6.7

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

+0

不是。你应该问的是“是否有更好的方式来分页我的结果”,并解释你的实际使用情况,而不是假设的情况。 –

+1

我试图获得5000批处理结果,以升序或降序方式处理文档中“hi”作为语言字段中的值。所以我使用这个查询,其中我每次通过递增“跳过”值跳过处理的文档。 – user2710961

+0

那里。现在看看你提出的问题是多少描述性的。请修改您的问题以包含该内容以及更合适的标题。这是一个很好的问题。你问的是一个可怕的问题。所以你只需要5000个,然后继续下一批,等等,对吗? –

回答

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操作符可以“过滤”您已处理的所有结果,因此您可以更快地移动。

3

当您想对降序排序时,您应该创建一个多字段索引,它使用您排序的字段作为降序字段。您通过将这些字段设置为-1来完成此操作。

该指数将大大增加你的某种表现:

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

如果你也想加快其他情况下 - 取回按升序排序 - 创建第二个指标是这样的:

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

请记住,当您不对结果进行排序时,您会按自然顺序收到它们。自然顺序是经常插入顺序,但不能保证。有各种事件可能导致自然顺序混乱,所以当你关心顺序时,你应该总是明确排序。这条规则的唯一例外是capped collections,它总是保持插入顺序。