Reputation: 147
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
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