Desty
Desty

Reputation: 2776

How to get _id after updating a MongoDB document?

I am using .Net MongoDB.Driver 2.2.3 and MongoDB 3.2. I want to get the _id of the document I insert or replace with collection.ReplaceOneAsync(), because I use it later on.

However the UpsertedId of the result is null if the operation was an update (it is set, if an insert happened).

What is the best way to determine the _id of the updated document?

var collection = GetMongoDatabase().GetCollection<BsonDocument>("foos");
var document = new BsonDocument
{
     {"foo", "new bar"}
};
var result = await collection.ReplaceOneAsync(
    Builders<BsonDocument>.Filter.Eq("foo", "bar"),
    document,
    new UpdateOptions {IsUpsert = true});
// I want to use result.UpsertedId here;

If I take a look at result after an update in Visual Studio's Immediate Window, I see:

?result
{MongoDB.Driver.ReplaceOneResult.Acknowledged}
    [MongoDB.Driver.ReplaceOneResult.Acknowledged]: {MongoDB.Driver.ReplaceOneResult.Acknowledged}
    IsAcknowledged: true
    IsModifiedCountAvailable: true
    MatchedCount: 1
    ModifiedCount: 1
    UpsertedId: null

Upvotes: 3

Views: 3759

Answers (1)

ocuenca
ocuenca

Reputation: 39326

As far I know ReplaceOneAsync method doesn't return the UpsertedId when the document is replaced, you will see that field with a value when the document is inserted. If you replace an existing document, you can check in your DB that the replacement document is going to have the same _id of the old document:

var collection = GetMongoDatabase().GetCollection<BsonDocument>("foos");
var d=collection.Find<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "bar")).FirstOrDefault();
var id = d["_id"].ToString();//Check your id here
var document = new BsonDocument
{
     {"foo", "new bar"}
};
var result = await collection.ReplaceOneAsync(
             Builders<BsonDocument>.Filter.Eq("foo", "bar"),
             document,
             new UpdateOptions {IsUpsert = true});

var d1=collection.Find<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "new bar")).FirstOrDefault();
var id1 = d1["_id"].ToString(); // You will see the same _id

Probably the method you are looking for is FindOneAndReplaceAsync:

var d =collection.FindOneAndReplace<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "new bar"), 
                                                  document,
                                                  new FindOneAndReplaceOptions<BsonDocument, BsonDocument>() 
                                                  { IsUpsert=true,
                                                    ReturnDocument=ReturnDocument.After
                                                  });
var id = d["_id"].ToString();

Upvotes: 3

Related Questions