2014-08-31 72 views
0

我正在處理一個系統,其中用戶能夠使用多個參數查詢我的MongoDB數據庫。當用戶查詢時,他們會得到20個結果。然而,用戶可能想獲得額外的20個結果,然後另一個等...MongoDB恢復舊查詢或跳轉到文檔

我編程這樣一個系統的第一個直覺是使用「跳過」功能,並跳過結果數已經返回給用戶;然而,與此相關的問題是,在用戶運行新查詢以獲取新結果所需的時間內,很多(數百或數千個)匹配用戶查詢的新文檔可能已添加到MongoDB中。因此,「跳過」將不會恢復查詢最後放出的位置。

例如,

Documents: 

1,2,3,4,5,6,7,8,9,10,11,12,13,14, etc... 

我們在文檔編號20處離開。用戶的下一個查詢說要跳過20.但是,已添加500個新文檔。現在跳過應該是520,以便在最後放出的地方提取查詢。但是,我目前無法跟蹤自上次查詢用戶以來添加了多少文檔。

我的下一個想法是讓用戶提交最後一個查詢中收到的最後一個文檔的Id以及用戶在所有查詢中收到的文檔總數。我會告訴MongoDB「跳過」用戶收到的文檔總數 - 1.然後,我會將每個文檔與用戶發送的文檔的ID進行比較,直到找到用戶離開的位置。

例子:

public static String getDocument(String lastId, int skip, BasicDBObject query) 
{ 
    DBCursor cursor = collection.find(query).skip(skip); 
    while(cursor.hasNext()) 
    { 
     BasicDBObject obj = (BasicDBObject) cursor.next(); 
     String id = obj.getString("id"); 
     if(id.equals(lastId)) 
     { 
     //Then we know that here is where we left off, and to start getting new documents 
     } 
    } 
} 

此,我認爲,如果是已經增加了許多新的文件效率低下,並且可能可能會讓查詢時間慢。這是否正確?

有沒有辦法查詢MongoDB,告訴它跳過給定的文檔ID之前的所有結果?如果沒有,是否有處理這個問題的標準方法?我不知道該怎麼做。

回答

2

不錯的問題。我不知道你爲什麼在這裏提到了一個「聚集」,從我的例子中看到它是一個mongo常規查詢,所以我假設你的問題是關於mongo查詢,而不是關於聚合框架。

爲了回答您的問題(至少據我瞭解),起初我想提供一些「提示和技巧」,如信息在這裏。

在mongo db中,有更多的原因可以避免跳過大量的對象,這是因爲當您使用「跳過X」查詢語句時,引擎必須遍歷所有X對象(線性掃描)所以如果你檢索,說200個對象,並使用跳過,獲得這200個對象的時間將逐漸增長,因爲跳過值增長。

這不是mongo所獨有的,順便說一句,這也發生在關係型數據庫中。

在這方面與Mongo一起使用的一種首選方式是通過您不關心的東西返回有序的結果,但它有一個索引(例如_id)。

請注意,從查詢中,你只是遍歷整個結果,而你並不關心這些結果的順序。 那麼你可以在這種情況下,做的是:

getNResults ordered by id (ascending) 
while(shouldRetrieveMoreResults()) { 
    memorize the last id in the list of retrieved results 
    instead of skip, use the following query: "get 200 objects ordered by id ascending where id > _a_memorized_id" 
    memorize the last id among retrieved ids and perform the loop again and again 
} 

由於_id總是上有一個索引,查詢將會很快也將成爲大跳過值更有效。

這是什麼寫在蒙戈DB本書,順便說一句:)

現在你這裏養的是另一個問題。基本上你說你有不斷變化的數據。 在這種情況下,可能最好的做法是在文檔中添加一些「輔助」字段,這個字段總是會像時間一樣增加,以便您可以按時間迭代值。時間可以被索引。所以你可能想使用上面描述的相同的技巧,但不是使用對象ID排序,而是使用另一個索引字段排序。

希望這會有所幫助