Issue Summary - When doing a pull filter against a nested array of objects using the Lt operator, Azure Cosmos Mongo API does not remove the expected elements.
.NET Version - .NET Core 3.1
MongoDB.Driver Version - 2.10.2
Here are the details for what I am trying to do and what is happening.
I have the following document
{
"_id" : ObjectId("5e80b59326773581903da606"),
"item" : "journal",
"instock" : [
{
"warehouse" : "A",
"qty" : 15
},
{
"warehouse" : "B",
"qty" : 5
},
{
"warehouse" : "C",
"qty" : 2
}
]
}
What I want to do is remove any elements from the "instock" array where qty is less than 10. Here is my C# code using the MongoDB.Driver nuget package where I try to do this.
static void Main(string[] args)
{
var item = "journal";
var collection = GetCosmosCollection();
collection.DeleteOne(i => i.item == item); // Delete the existing document
InsertSampleData(collection, item); // Insert the sample JSON document shown above
var filter = Builders<InventoryItem>.Filter.Eq("item", item);
// Remove from the instock array where qty is less than 10
var stockPullFilter = Builders<InventoryItem>.Update.PullFilter(
"instock",
Builders<Stock>.Filter.Lt(s => s.qty, 10)
);
collection.FindOneAndUpdate<InventoryItem>(
filter,
stockPullFilter
);
}
When I go view the collection in the Azure Cosmos data explorer, I still see all of the objects listed in "instock".
If I change the operator to "Eq" instead of "Lt", and match on an exact qty, then it works.
// Remove from the instock array where qty equals 5
var stockPullFilter = Builders<InventoryItem>.Update.PullFilter(
"instock",
Builders<Stock>.Filter.Eq(s => s.qty, 5)
);
So to me this seems to be a bug with using the Lt operator. I tried with Lte, Gt, and Gte and experience the same issue.
I then decided to spin up a collection using Mongo Atlas and see what happened. The same exact C# code works against Atlas using the Lt operator. So at this point it appears to just be an issue with Cosmos.
Next, I recreated this logic just using mongo shell commands in order to figure out if this is a problem with the mongo .net driver or with Cosmos.
// Delete the test item to make sure we start fresh
db.inventory.deleteOne( { "item": "journal" } )
// Insert a test item, with 3 instock elements
db.inventory.insertOne( { "item": "journal", "instock": [{warehouse: "A", qty: 15}, {warehouse: "B", qty: 5}, {warehouse: "C", qty: 2}] } );
// Find the test item to confirm it insert successfully
db.inventory.find( { "item": "journal" } ).pretty()
// Pull (remove) from the instock array where the quantity is less than 10
db.inventory.update({ item: "journal" }, { $pull: { instock: { qty: { $lt: 10 } } } }, { multi: true })
// Find the test item to confirm the stock is removed as expected
db.inventory.find( { "item": "journal" } ).pretty()
Executing this against Atlas works fine while executing this against Cosmos does not remove any instock elements.
Obviously this is an issue with Azure Cosmos' Mongo API implementation, but my question is this:
Is there some other way to write this pull command or will I need to reach out to Microsoft support and raise this issue with them?
Thanks