2012-11-08 88 views
1

我有一個包含許多文檔(可能是數百萬)的集合。當用戶插入一個新文檔時,我希望有一個字段來維護我可以索引的數據的「順序」。例如,如果一個字段是時間,以這種格式「1352392957.46516」,如果我有三個文檔,第一個是時間:1352392957.46516,第二個是時間:1352392957.48516(20ms之後),第三個是1352392957.49516(10ms之後)喜歡有另一個領域,其中第一個文檔將有0,第二個將是1,第三個2,依此類推。維護MongoDB集合的順序

我想要這個的原因是,我可以索引該字段,然後當我做一個查找時,我可以做一個有效的$ mod操作來下采樣數據。因此,例如,如果我有一百萬個文檔,並且我只希望它們中的1000個均勻分佈,我可以在整數字段上執行$ mod [1000,0]。

我無法在時間字段上做到這一點的原因是因爲它們可能不是完全隔開的,或者可能都是偶數或奇數,所以模塊不起作用。所以單獨的整數字段會以線性遞增的方式保持順序。

另外,您應該能夠在集合中的任何位置插入文檔,因此所有後續字段都需要更新。

有沒有辦法自動做到這一點?或者我會不得不實施這個?或者是否有更有效的方式來做我所描述的內容?

+1

此http:// WWW .mongodb.org/display/DOCS/How + to + Make + an + Auto + Incrementing + Field應該可以解決您的問題。 –

+0

爲什麼你需要「插入」一個文件?更新「所有後續整數」聽起來很痛苦。你有什麼理由不能添加到最後?整數是否應該是一個排序順序呢? – cirrus

+0

該整數應該是排序順序,因爲這是我能想到的有效降低數據採樣率的唯一方法。我希望用戶能夠插入可能比最終時間戳更早的舊數據。 –

回答

1

如果您正在爲單個插入更新數百萬個文檔,它將遠遠超出「較慢的插入」 - 此方法使您的整個集合成爲活動工作集。同樣,爲了執行$mod與鍵值的比較,您必須比較索引中的每個鍵值。

鑑於您對排序採樣訂單的要求,我不確定您是否可以採用更高效的preaggregation方法。

我會用skip() and limit()來獲取一個隨機文檔。該skip()命令將從每一次在不需要的文件,以跳過索引的開始掃描,但如果你有足夠的內存來保證指數在內存中的表現應該是可以接受的:

// Add an index on time field 
db.data.ensureIndex({'time':1}) 

// Count number of documents 
var dc = db.data.count() 

// Iterate and sample every 1000 docs 
var i = 0; var sampleSize = 1000; var results = []; 
while (i < dc) { 
    results.push(db.data.find().sort({time:1}).skip(i).limit(1)[0]); 
    i += sampleSize; 
} 

// Result array of sampled docs 
printjson(results); 
+0

我認爲這可能工作對我而言,我正計劃緩存查詢的結果。我只需要重新運行這種類型的查詢1000(本例中)更多的條目已被添加。 –

+0

我結束了使用地圖縮小。上面的答案證明太慢了。現在我所做的是使用mapReduce的範圍選項並保留外部計數和索引。我使用排序對輸入進行排序,並用僅包含我想要的文檔的數組構建結果文檔。這似乎很快。 –