2011-08-30 75 views
3

我有一個包含3種數字性質的化合物_id:MongoDB中複合_id的預期行爲?

_id「:{ 」KEYA「:0, 」KEYB「:0, 」KeyC「:0 }

在考慮中的數據庫具有用於KEYA和500k的相同的值的2000000倍相同的值集羣以KEYB

我的理解是,我可以爲KEYA和KEYB使用命令有效地查詢:

find({ "_id.KeyA" : 1, "_id.KeyB": 3 }).limit(100) 

當我解釋這個查詢的結果是:

"cursor" : "BasicCursor", 
"nscanned" : 1000100, 
"nscannedObjects" : 1000100, 
"n" : 100, 
"millis" : 1592, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"isMultiKey" : false, 
"indexOnly" : false, 
"indexBounds" : {} 

沒有限制()的結果是:

"cursor" : "BasicCursor", 
"nscanned" : 2000000, 
"nscannedObjects" : 2000000, 
"n" : 500000, 
"millis" : 3181, 
"nYields" : 0, 
"nChunkSkips" : 0, 
"isMultiKey" : false, 
"indexOnly" : false, 
"indexBounds" : {} 

據我瞭解BasicCursor意味着指數已經忽略,這兩個查詢有高執行時間 - 即使我只需要100個記錄,也需要1.5秒。我打算用限制來實現分頁,但這顯然太慢了。

的命令:

find({ "_id.KeyA" : 1, "_id.KeyB": 3, , "_id.KeyC": 1000 }) 

正確地使用BtreeCursor並執行快速暗示化合物_id是正確的。

我使用的MongoDB的版本1.8.3。有人可以澄清,如果我看到預期的行爲,或者我誤解了如何使用/查詢複合索引?

謝謝, 保羅。

回答

10

該指數是不是一個複合指數,但對整個價值指數_id字段。 MongoDB不會查看索引字段,而是使用字段的原始BSON表示形式進行比較(如果我正確地閱讀了文檔)。

做你想做什麼,你需要在{_id.KeyA: 1, _id.KeyB: 1, _id.KeyC: 1}實際複合索引(這也應該是唯一索引)。既然你不能沒有對_id索引你可能會更好把它當作ObjectId(這將創建一個較小的指數,浪費更少的空間),並保持你的KeyAKeyBKeyC字段作爲文檔的屬性。例如。 {_id: ObjectId("xyz..."), KeyA: 1, KeyB: 2, KeyB: 3}

+0

西奧 - 感謝,而你的回答是基本相同mstreams我已經接受你的答案,因爲你明確地指出,_id場沒有給我一個複合索引(這是我未能把握位) 。我天真地認爲,如果我在自動編制索引的_id字段上創建了一個複合鍵,那麼最終結果將是一個複合索引。你生活和學習。 – Paul

8

您需要一個單獨的複合索引來表達您所期望的行爲。一般來說,我建議不要將對象用作_id,因爲鍵比例在比較中很重要,所以{a:1,b:1}不等於{b:1,a:1}。由於不是所有的驅動程序中的對象保留鍵順序也很容易通過做這樣的事情來搬起石頭砸自己的腳:

db.foo.save(db.foo.findOne())