2012-07-06 21 views
1

這似乎是一個常見的用例...但不知何故,我無法得到它的工作。如何使用MongoDB作爲唯一/枚舉存儲

我正在嘗試使用MongoDB作爲具有唯一項目的枚舉存儲。我創建了一個帶有byte [] Id(唯一ID)和一個時間戳(一個long,用於枚舉)的集合。該商店相當大(千兆字節),並分佈在不同的服務器中。目前我能夠從零開始重建商店,因爲我仍處於測試階段。

我想要做的是兩兩件事:

  1. 創建我插入每個項目的唯一ID。這基本上意味着如果我插入兩次相同的ID,MongoDB將檢測到這個並給出錯誤。這種方法似乎很好。
  2. 通過其他進程連續枚舉新商品的商店。我採用的方法是爲InsertID添加第二個索引,並在服務器ID和計數器上使用高精度時間戳(僅用於使其唯一併且升序)。

在最好的情況下,這將意味着枚舉器會跟蹤每個服務器的索引遊標。從我從mongodb查詢處理中學到的東西,我預料到了這種行爲。但是,當我嘗試執行代碼(下面)時,似乎需要永遠得到任何東西。

 long lastid = 0; 
     while (true) 
     { 
      DateTime first = DateTime.UtcNow; 
      foreach (var item in collection.FindAllAs<ContentItem>().OrderBy((a)=>(a.InsertId)).Take(100)) 
      { 
       lastid = item.InsertId; 
      } 
      Console.WriteLine("Took {0:0.00} for 100", (DateTime.UtcNow - first).TotalSeconds); 
     } 

我已閱讀關於遊標,但我不確定是否滿足新條目插入商店時的要求。

正如我所說的,我沒有綁定到任何表結構或類似的東西......唯一重要的是我可以隨着時間的推移獲得新的項目,而不會獲得重複的項目。

-Stefan。

+0

我不確定如果我有你的問題!但是,爲什麼不讓mongodb生成uniqueId。它已經做到了! – 2012-07-06 12:04:40

+0

你需要的是確保一個字符串不被枚舉兩次,或者用另一種方式說兩個ID不應該有相同的值! – 2012-07-06 12:05:22

+0

聽起來好像你正在使用分片(*多個計算機*)。這裏你的碎片鑰匙是什麼?你有多少臺服務器?通過跨多個服務器的二級索引查詢可能是您的問題,但我需要更多關於您的配置的詳細信息。 – 2012-07-06 22:51:46

回答

0

不知怎的,我想通了...或多或少...

我手動創建的查詢,並結束了這樣的事情:

db.documents.find({「InsertId 「:{」$ gt「:NumberLong(」2020374866209304106「)}})。limit(10).sort({」InsertId「:1});

我放在問題中的LINQ查詢不會生成此查詢。後我發現,它應該是這樣的LINQ查詢代碼一些挖掘:。

的foreach(在collection.AsQueryable()VAR項目凡((A)=>(a.InsertId> lastid))排序依據((a)=>(a.InsertId))。取(100))

AsQueryable()似乎是執行重寫LINQ到MongoDB查詢的關鍵。

這給出了結果,但它們似乎仍然很慢(10次結果爲4秒,100次爲30次)。但是,當我添加'explain()'時,我在查詢執行中注意到'0毫秒'。

我停止了做批量插入和tada的過程,它的工作原理和快速。換句話說:我遇到的問題是由於MongoDB的鎖定行爲,以及由於我解釋linq實現的方式。由於前者是初始批量填充數據存儲的結果,這意味着問題得以解決。

在解決方案的'消極'部分:我會更喜歡一個解決方案,涉及可序列化遊標或類似的東西......這個'採取'的解決方案必須一遍又一遍地重複b-tree。如果有人有這個答案,請讓我知道。

-Stefan。

+0

1)因爲總是從一個id開始排序(這可能是編入索引的),所以我沒有看到自己在「遍歷」b-tree的位置,而不是從id和index中取出100個項目。不知道如何得到其中的100個...... – 2012-07-09 12:12:45

+0

2)你的問題提到了多個讀者。使用你這樣做的方式,是什麼阻止了兩個不同的讀者處理相同的記錄? – 2012-07-09 12:13:39

+0

@CraigWilson它沒有;我只是枚舉每個「進程」的相同集合(例如索引等)。這是說實話,我想要做的併發,但實際上我剛剛解決了5分鐘前的難題的部分:-) MongoDB有輝煌的事情,你可以連接到個別副本集並執行查詢。如果您擁有的進程數與副本集數量一樣多,則可以簡單地枚舉每個進程實例的一個副本集。其實這是我正在尋找的完整解決方案。順便說一下:這個能力是MongoDB imho的一個輝煌的USP。 – atlaste 2012-07-09 15:43:20