Mongodb update inline documents using multiple field matches with c # driver
I have a document structure on mongodb like below:
{
_id: <string>,
field1: ...,
field2: ...,
field3: ...,
DeviceVersionPairs: [{
DeviceId: <ObjectId>,
CloudFolderId: <ObjectId>,
CloudFileId: <ObjectId>,
VersionId: <ObjectId>,
Status: <int>
},{
DeviceId: <ObjectId>,
CloudFolderId: <ObjectId>,
CloudFileId: <ObjectId>,
VersionId: <ObjectId>,
Status: <int>
},
....
]
}
I wrote this mongodb query, it is for looking for a string with _id
specified than updating a subdocument in an array DeviceVersionPairs
matching a filter elemMatch
that actually works;
db.deduplications.update({
"_id": "...",
"DeviceVersionPairs": { "$elemMatch" : {
"DeviceId": ObjectId("..."),
"CloudFolderId": ObjectId("..."),
"CloudFileId": ObjectId("..."),
"VersionId": ObjectId("...")
}}
},{
"$set": { "DeviceVersionPairs.$.Status": 100 }
}, false, false)
But I cant convert it to use with C # driver (2.0.1.27). So far I have had it, but it is missing an instruction elemMatch
, so it doesn't work as expected.
var p = DbContext.Deduplications.FindOneAndUpdateAsync(
filter: Builders<Dal.Deduplication>.Filter.And(
Builders<Dal.Deduplication>.Filter.Eq("_id", fileHash),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.DeviceId", deviceId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.CloudFolderId", CloudFolderId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.CloudFileId", FileId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.VersionId", versionIdToBeRemoved)),
update: Builders<Dal.Deduplication>.Update.Set("DeviceVersionPairs.$.Status", DVPStatus.PassiveOrDeleted)).Result;
What is the way to make such a mongodb request using the C # driver?
source to share
Finally I came up with my own solution. Creating a filter using regular objects BsonDocument
did the job.
var filter = new BsonDocument(new List<BsonElement> {
new BsonElement("_id", fileHash),
new BsonElement("DeviceVersionPairs", new BsonDocument("$elemMatch", new BsonDocument(new List<BsonElement> {
new BsonElement("DeviceId", deviceId),
new BsonElement("CloudFolderId", cloudFolderId),
new BsonElement("CloudFileId", cloudFileId),
new BsonElement("VersionId", versionId)
})))
});
source to share
Are you trying to match any element within the array? If so, then this should work:
var p = DbContext.Deduplications.FindOneAndUpdateAsync(
filter: Builders<Dal.Deduplication>.Filter.AnyEq(
Builders<Dal.Deduplication>.Filter.Eq("_id", fileHash),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.DeviceId", deviceId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.CloudFolderId", CloudFolderId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.CloudFileId", FileId),
Builders<Dal.Deduplication>.Filter.Eq("DeviceVersionPairs.VersionId", versionIdToBeRemoved)),
update: Builders<Dal.Deduplication>.Update.Set("DeviceVersionPairs.$.Status", DVPStatus.PassiveOrDeleted)).Result;
source to share