2015-07-06 45 views
0

我正在嘗試使用php驅動程序計算mongo db集合中給定記錄的跳過值。因此,記錄一個給定的記錄,找出整個集合中該記錄的索引。這可能嗎?爲排序尋呼計算給定記錄的跳過值

目前我正在選擇所有記錄並手動對結果數組進行索引。

回答

4

這就是所謂的「向前分頁」,這是一個概念,當您使用「排序」結果時,您可以使用「有效分頁」結果以「向前」方向結果。

包括JavaScript邏輯(因爲它在shell中工作),但不難翻譯。

一般的概念:作爲結果的例子

{ "_id": 1, "a": 3 }, 
{ "_id": 2, "a": 3 }, 
{ "_id": 3, "a": 3 }, 
{ "_id": 4, "a": 2 }, 
{ "_id": 5, "a": 1 }, 
{ "_id": 6, "a": 0 } 

考慮那些「已經排序」的文件(convienience)我們要「頁」每頁「兩化」項目。

在第一種情況下,你做這樣的事情:

var lastVal = null, 
    lastSeen = []; 

db.collection.find().sort({ "a": -1 }).limit(2).forEach(function(doc) { 
    if (lastVal != doc.a) { 
     lastSeen = []; 
    } 
    lastVal = doc.a; 
    lastSeen.push(doc._id); 
    // do something useful with each document matched 
}); 

現在那些lastVallastSeen是你的東西存儲就像一個「會話變量」不是可以下一個請求在網絡方面進行訪問的東西應用程序,或其他類似的地方沒有。

它們應該包含的內容是您正在排序的最後一個值以及自該值未發生變化後出現的「唯一」_id值列表。因此:

lastVal = 3, 
lastSeen = [1,2]; 

的一點是,當「下一頁」的要求,惡有惡報,那麼你要使用這些變量是這樣的:

var lastVal = 3, 
    lastSeen = [1,2]; 

db.collection.find({ 
    "_id": { "$nin": lastSeen }, 
    "a": { "$lte": lastVal } 
}).sort({ "a": -1 }).limit(2).forEach(function(doc) { 
    if (lastVal != doc.a) { 
     lastSeen = []; 
    } 
    lastVal = doc.a; 
    lastSeen.push(doc._id); 
    // do something useful with each document matched 
}); 

那是什麼做的是「排除」從結果列表中記錄在lastSeen中的所有_id的值,以及確保所有結果都需要爲排序字段「a」記錄的lastVal「小於或等於」(降序)。

這產生了接下來的兩個結果集合中:

{ "_id": 3, "a": 3 }, 
{ "_id": 4, "a": 2 }, 

但處理我們的價值觀後,現在看起來是這樣的:

lastVal = 2, 
lastSeen = [4]; 

所以,現在的邏輯如下,你不需要排除之前看到的其他_id值,因爲您只是真的在尋找「a」的值而不是「小於或等於」lastVal,並且因爲在該值處僅顯示「1」_id值,所以只排除第在一個。

這當然產生於使用相同的代碼上面剛剛下頁:

{ "_id": 5, "a": 1 }, 
{ "_id": 6, "a": 0 } 

這是最effiecient的方式「向前翻頁」通過一般的結果,是特別有用有效地分頁「排序」結果。

如果你想跳到頁面20或者任何階段的類似動作,那麼這不適合你。你堅持使用傳統的.skip().limit()的方法能夠通過「頁碼」來完成這一工作,因爲沒有其他合理的方法來「計算」這一點。

所以這一切都取決於你的應用程序如何實現「分頁」以及你可以忍受的。 .skip().limit()方法遭受「跳過」的性能,並且可以通過使用這裏的方法來避免。另一方面,如果你想「跳轉到頁面」,那麼「跳過」是你唯一真正的選擇,除非你想建立一個「緩存」的結果。但這完全是另一個問題。

+0

夢幻般的答案,非常感謝:) – Garbit