2014-02-22 36 views
6

我有一個文檔的ID,需要返回文檔加上之前的10個文檔和之後的10個文檔。共有21篇文章。MongoDB中圍繞ID的文檔的返回範圍

我沒有任何鍵的開始或結束值。只有兩個方向的限制。

最好的方法來做到這一點?先謝謝你。

+0

不幸的是我相信你會被卡住運行一個'.find()'來獲取整個集合,迭代直到你找到你的目標文檔,然後獲得下一個+10/-10 - 你需要一個遊標,來自'.find()' – tymeJV

+0

@tymeJV我不這麼認爲。查看答案 –

+0

@NeilLunn - 那真是太棒了! +1 – tymeJV

回答

5

您是否知道ObjectID's包含時間戳?因此,他們總是代表自然的插入順序。所以,如果你是一個已知的文件後之前找文件_id你可以這樣做:

我們的文件:

{ "_id" : ObjectId("5307f2d80f936e03d1a1d1c8"), "a" : 1 } 
{ "_id" : ObjectId("5307f2db0f936e03d1a1d1c9"), "b" : 1 } 
{ "_id" : ObjectId("5307f2de0f936e03d1a1d1ca"), "c" : 1 } 
{ "_id" : ObjectId("5307f2e20f936e03d1a1d1cb"), "d" : 1 } 
{ "_id" : ObjectId("5307f2e50f936e03d1a1d1cc"), "e" : 1 } 
{ "_id" : ObjectId("5307f2e90f936e03d1a1d1cd"), "f" : 1 } 
{ "_id" : ObjectId("5307f2ec0f936e03d1a1d1ce"), "g" : 1 } 
{ "_id" : ObjectId("5307f2ee0f936e03d1a1d1cf"), "h" : 1 } 
{ "_id" : ObjectId("5307f2f10f936e03d1a1d1d0"), "i" : 1 } 
{ "_id" : ObjectId("5307f2f50f936e03d1a1d1d1"), "j" : 1 } 
{ "_id" : ObjectId("5307f3020f936e03d1a1d1d2"), "j" : 1 } 

因此,我們知道的「F」的_id,得到它,接下來的2個文件:

> db.items.find({ _id: {$gte: ObjectId("5307f2e90f936e03d1a1d1cd") } }).limit(3) 

{ "_id" : ObjectId("5307f2e90f936e03d1a1d1cd"), "f" : 1 } 
{ "_id" : ObjectId("5307f2ec0f936e03d1a1d1ce"), "g" : 1 } 
{ "_id" : ObjectId("5307f2ee0f936e03d1a1d1cf"), "h" : 1 } 

,做同樣的反向:

> db.items.find({ _id: {$lte: ObjectId("5307f2e90f936e03d1a1d1cd") } }) 
    .sort({ _id: -1 }).limit(3) 
{ "_id" : ObjectId("5307f2e90f936e03d1a1d1cd"), "f" : 1 } 
{ "_id" : ObjectId("5307f2e50f936e03d1a1d1cc"), "e" : 1 } 
{ "_id" : ObjectId("5307f2e20f936e03d1a1d1cb"), "d" : 1 } 

這就是很多比掃描集合更好的方法。

1

Neil的回答是所述問題的一個很好的答案(假設您使用的是自動生成的ObjectId),但請記住,在給定文檔之前和之後的10個文檔的概念之間存在一些細微差別。

ObjectId的完整格式記錄在here。請注意,它包括以下字段:

  • 時間戳1秒的分辨率,
  • 機器標識符
  • 進程ID
  • 計數器

一般來說,如果你不指定它們是由客戶端機器上的驅動程序自動生成的。因此,只要客戶端單機上的單個進程生成ObjectIds,它們的順序確實反映了它們的生成順序,在典型的應用程序中它們也將是插入順序(但不一定是)。但是,如果您有多個進程或多臺客戶端計算機,則這些多個源在給定秒內生成的對象的ObjectIds順序與插入順序具有不可預知的關係。