2016-12-12 80 views
0

我有一個巨大的收藏與〜10億文件,這些文件(少於200)包含一些字段「rare_field」很少。快速搜索非常罕見的領域在一個巨大的mongodb集合

我該如何儘快找到包含該字段的所有文檔?

如果我簡單地做:

collection.find({ "rare_field" : { $exists : true }}) 

超時。 這可能需要數天時間才能完成,所以我不確定即使通過查詢標誌防止超時也會有所幫助,但也許我錯了。

我也可以編寫一個腳本來查看所有文檔,但這樣會很慢,因爲它需要將所有10億個文檔通過網絡傳遞到我的服務器,我想要一些不需要任何數據傳遞的解決方案在電線上,並且會很快。

備註:這是一個sharded集合。

我將發佈我當前的解決方案作爲答案,但我不確定它是100%正確的,並沒有我想要的那麼快。

+0

將這個'rare-field'放入分片查詢中!正因爲如此,mongo也會對這個領域進行索引!所以它會很快! –

+0

謝謝。這是一次性的事情,所以我並不需要索引。 這可能是一個很好的解決方案,當數據庫是空的,但索引這個領域現在需要很多時間,就像手工檢查所有文檔(我認爲) – marmor

+0

你是正確的時間消耗!所以這完全取決於你的應用程序!另一種方法是將結果保存在緩存中!將結果存儲在新的集合中,或存儲在redis或smtn中! –

回答

2

沒有索引rare-field,在最壞的情況下,mongodb將需要檢查集合中的所有文檔。在這種情況下,光標可能會超時,所以您需要向光標添加一個標誌以防止這樣做。

在蒙戈外殼,這將意味着像查詢:

var cursor = db.collection.find({ "rare_field" : { $exists : true }}).noCursorTimeout(); 

如果您關注的是,網絡問題或其他問題將中斷查詢之前光標已經填充了batchSize匹配的文件,那麼你確實可以得到的文件逐一爲你在你的答案建議,但是你需要通過{ _id: 1 }進行排序,並使用noCursorTimeout()limit(1),即:

var doc = db.collection.find({ "rare_field" : { $exists : true }}) 
      .sort({ _id: 1 }) 
      .limit(1) 
      .noCursorTimeout() 
      .next(); 

然後按照您的建議,通過重複查詢,同時將{ _id: { $gt: doc._id } }條件添加到查詢對象來檢索下一個文檔。

0

一個可能的解決方案是使用findOne,而不是發現的:

var doc = collection.findOne({ "rare_field" : { $exists : true }}); 

,然後循環,以獲得下一個:

var doc = collection.findOne({ _id : { $gt : doc._id}, "rare_field" : { $exists : true }}); 

不過,我不是100%肯定的是,這些電話必須給我_id訂購的結果,我不確定單個findOne也不會超時。

我擔心明確添加sort({_id : 1})會強制查詢獲取所有結果,然後傳遞第一個結果。

+0

我不認爲這會是一個好主意!就像你做最糟糕的事情一樣!你是mongo會做'find({「rare_field」:{$ exists:true}});'會做!但是你有很多開銷將它分成幾塊。 –

+0

你的恐懼也有點解釋你爲什麼不應該這樣做!:) –