I’m trying to upsert a document into Mongo using the C# Driver with the following (simplified) method:
public MyDocumentType UpsertOne(MyDocumentType doc)
{
var options = new FindOneAndReplaceOptions<MyDocumentType>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After,
};
var filter = Builders<MyDocumentType>.Filter.Eq(d => d.Id, doc.Id);
var upsertedDoc = _collection.FindOneAndReplace(filter, doc, options);
return doc;
}
Neither the upsertedDoc
nor doc
objects have a nonzero objectID.
However, When I insert the doc with InsertOne()
Mongo generates a docID
as expected:
public MyDocumentType InsertOne(MyDocumentType doc)
{
_collection.InsertOne(doc);
return doc;
}
The ObjectId
field in my document class is nonnullable, and initializes to zeros, but on InsertOne it gets proper documentID
but when using FindOneAndReplace
with the IsUpsert=true
option it simply inserts a doc with a zero’d Id.
Here is how I’m calling the various methods, and the output:
var db = new MongoService();
db.Connect();
var documentWithZeroedId = db.UpsertOne(document);
Console.WriteLine($"Upsert Document ID: {documentWithZeroedId.Id}");
var documentWithValidId = db.InsertOne(document);
Console.WriteLine($"Insert Document ID: {documentWithValidId.Id}");
// Output:
Connected to Mongo!
Upsert Document ID: 000000000000000000000000
Insert Document ID: 6620b59ca4421c3c294c0b09
What is the proper means to upsert a doc and when inserting, get a valid non-zeroed doc ID?
The complete console app demonstrating this issue is:
using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using System.Security.Cryptography.X509Certificates;
using System.Xml.Xsl;
public class DictionaryValue
{
public int Id;
public string Value;
}
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public class BsonCollectionAttribute : Attribute
{
public string CollectionName { get; }
public BsonCollectionAttribute(string collectionName)
{
CollectionName = collectionName;
}
}
[BsonCollection("Documents")]
public class MyDocumentType
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
public ObjectId Id;
public DateTime CreatedAt => Id.CreationTime;
public string TopLevelField;
public Dictionary<string, DictionaryValue> Values;
}
class MongoService {
private MongoClient _client;
private IMongoDatabase _db;
private IMongoCollection<MyDocumentType> _collection;
public void Connect()
{
try
{
var settings = MongoClientSettings.FromConnectionString("mongodb://localhost:27018");
_client = new MongoClient(settings);
_db = _client.GetDatabase("dictionaryTest");
Console.WriteLine("Connected to Mongo!");
_collection = _db.GetCollection<MyDocumentType>("Documents");
}
catch (Exception ex)
{
Console.WriteLine("Error on connect to Mango database: {error}", ex);
throw;
}
}
public MyDocumentType UpsertOne(MyDocumentType doc)
{
var options = new FindOneAndReplaceOptions<MyDocumentType>
{
IsUpsert = true,
ReturnDocument = ReturnDocument.After,
};
var filter = Builders<MyDocumentType>.Filter.Eq(d => d.Id, doc.Id);
var upsertedDoc = _collection.FindOneAndReplace(filter, doc, options);
return doc;
}
public MyDocumentType UpsertOneSlow(MyDocumentType doc)
{
var existing = _collection.Find(d => d.Id == doc.Id).FirstOrDefault();
if (existing != null)
{
_collection.ReplaceOne(d => d.Id == doc.Id, doc);
return doc;
} else
{
_collection.InsertOne(doc);
return doc;
}
}
public MyDocumentType InsertOne(MyDocumentType doc)
{
_collection.InsertOne(doc);
return doc;
}
}
class Program
{
static int Main(String[] args)
{
var document = new MyDocumentType();
document.TopLevelField = "Dictionary of Integers";
document.Values = new Dictionary<string, DictionaryValue>()
{
{ "1", new DictionaryValue {Id = 1, Value = "1"} },
{ "2", new DictionaryValue {Id = 2, Value = "1"} },
{ "3", new DictionaryValue {Id = 3, Value = "2"} },
};
var db = new MongoService();
db.Connect();
var documentWithZeroedId = db.UpsertOne(document);
Console.WriteLine($"Upsert Document ID: {documentWithZeroedId.Id}");
var documentWithValidId = db.InsertOne(document);
Console.WriteLine($"Insert Document ID: {documentWithValidId.Id}");
return 0;
}
}