Home > other >  UpdateOneModel, with Upsert - error _id Mongodb C# MongoDB.Driver
UpdateOneModel, with Upsert - error _id Mongodb C# MongoDB.Driver

Time:02-04

I am trying to perform a bulkwrite with c# https://mongodb.github.io/mongo-csharp-driver/2.7/reference/driver/crud/writing/#bulk-writes - I could have a list of documents from 70-80K.

var correlationIdFilter = Builders<BsonDocument>.Filter.AnyIn("CorrelationId", ninKeysRecon);
var missingData = collection.Find(correlationIdFilter).ToList();

Missing Data Data Sample

{ 
    "_id" : ObjectId("61dd323bfe35f25bb2dcde8e"), 
    "CorrelationId" : "17bd621d-e47f-4ab1-9004-9543294a4549", 
    "Key" : "123", 
    "Date" : "2016-06-28T00:00:00", 
    "CurrentDate" : ISODate("2022-01-11T07:31:07.011 0000"), 
    "SourceSystem" : "abc", 
    "SourceEntity" : "source"
},
{ 
    "_id" : ObjectId("61dd323bfe35f25bb2dcd123"), 
    "CorrelationId" : "18bd621d-e47f-4ab1-9004-9543294a4549", 
    "Key" : "123232324", 
    "Date" : "2016-06-28T00:00:00", 
    "CurrentDate" : ISODate("2022-01-11T07:31:07.011 0000"), 
    "SourceSystem" : "abc", 
    "SourceEntity" : "source"
},
.
.
.
{100K Documents}

Then I createoptions and bulkOps

var options = new UpdateOptions { IsUpsert = true };
var bulkOps = new List<WriteModel<BsonDocument>>();

I dont know if I need to loop through missingData to create a new UpdateOneModel() but I am struggling to see where or how to create a filter because when I set _id as a filter, I get the error _id field is immutable. I do not want to overwrite the _id but I simply want to achieve something like this

collection.UpdateMany(correlationIdFilter, missingBson, options);

Or if I have to create a for loop, I have tried:

foreach(var data in missingBson)
{
    var upsert = new UpdateOneModel<BsonDocument>(
    new BsonDocument("_id", 1),
    new BsonDocument("$set", data)) { IsUpsert = true };
    bulkOps.Add(upsert);
}

collection.BulkWrite(bulkOps);

I get the error:

WriteErrors: [ { Category : "Uncategorized", Code : 66, Message : "Performing an update on the path '_id' would modify the immutable field '_id'" } ].'

removing - { IsUpsert = true } runs fine but doesn't do any upserting which I need.

Thank you

CodePudding user response:

The first argument passed to UpdateOneModel is the filter. The filter tells MongoDB which document you want to update. You pass new BsonDocument("_id", 1), which tells MongoDB you want to update the document with an _id of 1. _id is a special field in MongoDB documents:

The field name _id is reserved for use as a primary key; its value must be unique in the collection, is immutable, and may be of any type other than an array. If the _id contains subfields, the subfield names cannot begin with a ($) symbol

_id is immutable, meaning it cannot be changed. This is an issue because the data you are passing to $set contains an _id field that is not 1.

Instead, in the filter document you should be passing the _id of the document you are trying to insert.

foreach(var data in missingBson)
{
    var upsert = new UpdateOneModel<BsonDocument>(
    new BsonDocument("_id", data._id),
    new BsonDocument("$set", data)) { IsUpsert = true };
    bulkOps.Add(upsert);
}

This way the _id fields match, and you are not attempting to update a document with an _id of 1 for each write operation.

  •  Tags:  
  • Related