Greg
Greg

Reputation: 147

Using the MongoDB C# Driver (2.0) how might you specify and UpdateDefinition that will ignore properties with null values

Contact poco has 5 props - Id, FirstName, LastName, Phone, Email. Phone and Email are initially null and they are not referenced by client - they are in poco for "future" use. The UpdateDefinition specifies .Set constructs for each property but doing this will add Email and Phone to the document even though they are null - how do we avoid this?

Upvotes: 1

Views: 2553

Answers (1)

mnemosyn
mnemosyn

Reputation: 46311

It seems that's not possible. We'd have to ask the authors, but it looks like this is a deliberate choice and I believe it makes sense. Even if you use [BsonIgnoreIfNull] and [BsonIgnoreIfDefault] on the field, an explicit Set() will still translate more or less directly to $set. The Set() method is a very thin wrapper that will create a BsonDocument which is then sent to the server.

The thing is, if this was different, it'd mean that using Set with value null translates to a $unset which would seem really weird and counter-intuitive.

The key problem seems to be the use of a ton of explicit atomic operations - why don't you simply replace the document? In a document database, that is most straightforward approach, and $set really only makes sense if you have different writers to an object and you want to selectively update only one or two fields, or if the document seems to large to pipe back and forth so, again selectively, you only want to update a few fields. Using $set on the entire object seems useless to me. If you have an SQL background, remember that the query language is quite different in that SQL doesn't have a replace operation, it always uses explicit set statements.

EDIT: To solve this in an embedded array, the $ positional update operator will do the trick, so you can $set the entire embedded document:

db.customers.update(
   { "contacts.id" : contactIdToReplace },
   { $set: { "contacts.$" : { "email" : "foo", ... } } }
)

In C#, this translates to

collection.UpdateOneAsync(
  Builders<Customer>.Filter.Eq("Contacts.Id", contact.Id), 
  Builders<Customer>.Update.Set("Contacts.$", 
     new Contact { Email = null })).Wait();

With [BsonIgnoreIfNull] on the Email property in Contact, this will work as desired.

Upvotes: 2

Related Questions