2013-10-15 65 views
3

我有一個MongoDB集合(「用戶」),其中包含一個字典字段(「UserRegistrations」)。

字段定義是:

BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] 
    public Dictionary<string, UserRegistration> UserRegistrations = new Dictionary<string, UserRegistration>(); 

這是它由一個密鑰(字符串)和自定義對象作爲值的字典。

這是如何體現在MongoDB中:

"UserRegistrations" : [{ 
    "k" : "517ba4e1696b03108ccef51a", 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
}], 

當我使用$ AddToSet,如下面的例子:

IMongoQuery query = Query.EQ("_id", new ObjectId(uid)); 

var kvp = new KeyValuePair<string, UserRegistration>("517ba4e1696b03108ccef51a", new UserRegistration() 
{ 
RegistrationDate = DateTime.Now.ToUniversalTime(), 
}); 

IMongoUpdate update = Update.AddToSet("UserRegistrations", kvp.ToBsonDocument()); 

collection.Update(query, update, UpdateFlags.Multi); 

它不檢查,如果相同的密鑰已經存在,造成了在Dictionary字段中重複,後來在MongoDB C#驅動程序中導致反序列化錯誤。

我怎樣才能確保相同的密鑰不存在了?

謝謝!

回答

0

感謝您的回答,但這不是我正在尋找的。

將集合分隔爲另一個「UserRegistrations」集合是計數器NoSQL方法,後者需要昂貴的索引。我不需要16mb,實際上大約1mb就足夠了,所以這不是我的專業版。

我需要一個NoSQL,像o(1)通過UID直接訪問數據。

在我的應用程序中編輯文檔的第二種方法對我來說也不好,如果第一次調用獲取當前文檔並且第二次調用獲取它,則此方法可以異步調用,同時數據將會衝突,並會有一個未知結果的競爭條件。

我需要的是一個MongoDB解決方案($ AddToSet或類似的一行函數)。

經過一番研究 - 目前,沒有MongoDB函數實現這一點。

無論如何,我通過簡單地向Update語句添加一個限定條件來使用一個小操作,它首先檢查具有這種ID的鍵是否已經存在。

答:

IMongoQuery query = Query.And("_id", new ObjectId("RootDocumentKey")), Query.NE(string.Format("{0}.k", "FieldName"), BsonValue.Create("DictionaryKey"))); 

其中 「RootDocumentKey」, 「字段名」 和 「DictionaryKey」 是你的參數。

希望MongoDB很快就會添加這個功能。

1

在您的模式的當前狀態,我不認爲它是可能實現你正在嘗試使用只有一個更新查詢mongodb。

你有兩個選擇(也許更多的,我沒有想到的)

1.編輯文檔的程序

而不是僅僅用鍵值更新您的文檔你要追加,

  • 查詢數據庫整個文檔,
  • 把它變成一個本地C#TDocument對象,
  • 將您的鍵值對追加到文檔的本地副本上,確保您不添加已存在的鍵,並使用Save document方法將其更新到數據庫中。

這種方法非常慢(與直接更新相比),但它是在不改變模式的情況下執行所要求的唯一方法。

2.更改您的模式

有一個單獨的集合(名爲「UserRegistrations」爲了便於理解),每個鍵值對,(我猜測,其中包括陣列「UserRegistrations」對象,還有一些其他字段,如UserID或類似的)從鍵值對創建UserID和密鑰的唯一索引複合索引。

該集合中的記錄是這樣的:

{ 
    "UserID" : "unique_user_id_of_user_A" 
    "k" : "517ba4e1696b03108ccef51a", 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 
{ 
    "UserID" : "unique_user_id_of_user_B" 
    "k" : "jkfadifhafo4ho34fo78h34fo7",  #obvious keyboard spazzing here 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T19:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 
{ 
    "UserID" : "unique_user_id_of_user_A"  #same user as first record 
    "k" : "sfahoihu43o43f7437843f8g348",  #different key-value pair 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-22T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 

臨:您再也不用擔心每個文件16MB的限制,每個用戶都可以擁有幾乎無限的「UserRegistrations」(無論是什麼)。Con:你必須使用索引執行可能快速的連接,但是當使用mongodb時,你應該儘量避免使用它們。

這只是您提出問題的快速解決方案。如果你有興趣,你應該研究如何構建你的模式。 MongoDb data modelling manualthis question應該讓你開始。

+0

嗨,謝謝你的回答,但這不是我正在尋找的。 將集合分隔爲另一個「UserRegistrations」集合是計數器NoSQL方法,後者需要昂貴的索引。我不需要16mb,實際上大約1mb就足夠了,所以這不是我的專業版。 在我的應用程序中編輯文檔的另一種方法對我也不好,如果第一次調用獲取當前文檔,第二次調用獲取它,則此方法可以異步調用,同時,數據將會發生衝突。 我需要的是一個MongoDB解決方案(AddToSet或類似的)。 – mnnsx

+0

+1謝謝,幫助我! – Aaron