Search code examples
c#mongodbmongodb-.net-drivermongodb-query

$AddToSet to Dictionary (MongoDB, C#) duplicate entries


I have a MongoDB collection ("Users") which holds a dictionary field ("UserRegistrations").

The field definition is:

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

It's a dictionary which consists of a key (String) and a customized object as value.

This is how it reflects in MongoDB:

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

When I use $AddToSet, as following example:

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);

It doesn't check if the same key exists already, causing a duplication in a Dictionary field which later causes deserialization errors in MongoDB C# driver.

How can I make sure the same key doesn't exists already?

Thanks!


Solution

  • Thanks for the answer, but this isn't what I was looking for.

    Separating the collection to another "UserRegistrations" collection is counter NoSQL methodology which will later require an expensive indexing. I don't need 16mb, actually about 1mb is more than enough so this isn't a pro for me.

    I need a NoSQL like o(1) direct access to the data by UID.

    The second method of editing the document in my application is not good for me either, this method can be called asynchronously, if first call gets the current document and second call gets it to, in the meantime, the data will be conflicted and there will be a race condition with unknown results.

    What I need is a MongoDB solution ($AddToSet or similar one line function).

    After some research - currently, there is no MongoDB function that implements this.

    Anyway, I ended up using a small manipulation, by simply adding a qualification to the Update statement, which first checks if a key with such ID already exists.

    Answer:

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

    In which "RootDocumentKey", "FieldName" and "DictionaryKey" are your parameters.

    Hopefully MongoDB will add this functionality soon.