MongoDB C# Driver 2.0 - Update document
Asked Answered
I

4

45

I'm currently upgrading my code to MongoDB C# driver 2.0 and I'm having issues upgrading the code to update documents.

using the old version I was able to do something like this:

MyType myObject; // passed in 
var collection = _database.GetCollection<MyType>("myTypes");
var result = collection.Save(myObject);

I'm struggling to find a way to do this in the new version. I have found a few examples of updating single fields like

var filter = Builders<MyType>.Filter.Eq(s => s.Id, id);
var update = Builders<MyType>.Update.Set(s => s.Description, description);
var result = await collection.UpdateOneAsync(filter, update);

I'd like to update all the fields as I was doing in the old version with the method Save.

Any ideas ?

Thanks a lot

Interdictory answered 15/5, 2015 at 10:19 Comment(1)
check out the mongodb wrapper library MongoDB.Entities. updating an entity is as simple as: var author = DB.Find<Author>("ObjectId"); author.Name = "Charles Dickens"; author.Save();Escalade
T
49

I think you're looking for ReplaceOneAsync():

MyType myObject; // passed in 
var filter = Builders<MyType>.Filter.Eq(s => s.Id, id);
var result = await collection.ReplaceOneAsync(filter, myObject)
Tye answered 15/5, 2015 at 12:11 Comment(4)
Thanks mnemosyn ! I was just about to post my own answer as I just found the ReplaceOneAsync a few minutes ago. Thanks anyway that's exactly what I needed !Interdictory
Where are you getting the value for "id" from?Oldwife
I think it's better if you work with BsonDocument instead of MyType. If MyType has BsonIgnoreExtraFields flag, the document will ignore fields that are not represented in MyType class. In insert method, method will only insert fields that exists in class and you will lose all other nonrepresented fields.Tanatanach
@JurePotocnik: On the other hand, other decorators will be ignored... In any case, you need some kind of invariant checking, preferably in the object code imho. But the OP's question wasn't on the pros and cons of different migration strategies, which is a more complex topic I'm afraid.Tye
A
33

To add to mnemosyn's answer, while a simple ReplaceOneAsync does update a document it isn't equivalent to Save as Save would also insert the document if it didn't find one to update.

To achieve the same behavior with ReplaceOneAsync you need to use the options parameter:

MyType myObject; 
var result = await collection.ReplaceOneAsync(
    item => item.Id == id, 
    myObject, 
    new UpdateOptions {IsUpsert = true});
Aleras answered 15/5, 2015 at 17:34 Comment(7)
What driver version are you in? I have tried 2.01 and 2.2.2. There UpdateOptions is not allowed. Required option type is "FindOneAndReplaceOptions<MyType, TProjection>". I have no clue on how to create that with an IsUpsert setting.Orr
@JakobLithner My code calls ReplaceOneAsync. are you sure you're not calling FindOneAndReplaceAsync?Aleras
Aaaah, there we are!!!! It is very much friday afternoon here. I need to take brake ... Thanks a lot :)Orr
Is there any way to achieve the same thing without changing the document ID? By the same thing, I mean doing a simple Idempotent "Upsert" operation, providing a new version of the document without specifying specific fields that have changed.Hyalo
@Hyalo this doesn't change the document idAleras
Can this be done in a single batch call? or does each document have to be updated in some kind of loop? It seems there is a way to do updates, but it only updates a single field OR you can do the whole record one at a time. It would be nice to know how to update an entire IEnumerable<T> in one call.Gleanings
@Gleanings https://mcmap.net/q/374302/-is-a-mongodb-bulk-upsert-possible-c-driverAleras
V
8

you can use LINQ as following:

await context.collection.ReplaceOneAsync(b=> b.Id == item.Id,item);
Verret answered 22/12, 2015 at 16:56 Comment(0)
Y
1

use ObjectId.Parse(id)

var filter = Builders<MyType>.Filter.Eq(s => s.Id, ObjectId.Parse(id));
var update = Builders<MyType>.Update.Set(s => s.Description, description);
var result = await collection.UpdateOneAsync(filter, update);
You answered 24/1, 2021 at 6:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.