2015-07-28 146 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,它總是保持插入順序。