如何使用C#驱动程序从MongoDB文档中删除嵌套数组元素

15

我是MongoDB世界的新手,现在我正苦恼于如何删除、更新文档中嵌套数组字段中的元素。这是我的示例文档:

{
    "_id" : ObjectId("55f354533dd61e5004ca5208"),
    "Name" : "Hand made products for real!",
    "Description" : "Products all made by hand",
    "Products" : [ 
        {
            "Identifier" : "170220151653",
            "Price" : 20.5,
            "Name" : "Leather bracelet",
            "Description" : "The bracelet was made by hand",
            "ImageUrl" : "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQii6JCvXtx0iJGWgpvSl-KrdZONKYzDwS0U8uDvUunjO6BO9Aj"
        }
    ]
} 
在我的方法中,我获取文档的ID和我想要删除的产品的ID(标识符)。请问有人能告诉我如何从“产品”字段中删除具有标识符为170220151653的元素吗?
我尝试过:
var query = Query.And(Query.EQ("_id", categoryId), Query.EQ("Products.Identifier", productId));
var update = Update.Pull("Products", new BsonDocument() { { "Identifier", productId } });
myDb.Applications().Update(query, update);

如此建议:MongoDB从子文档中删除一个子文档

但是在

myDb.Applications()

处我遇到了一个错误。它无法被找到。

已解决:

var pull = Update<Category>.Pull(x => x.Products, builder => builder.EQ(q => q.Identifier, productId));
collection.Update(Query.And(Query.EQ("_id", ObjectId.Parse(categoryId)), Query.EQ("Products.Identifier", productId)), pull);

你是想要删除仅仅 标识符 还是整个数组? - Neo-coder
@yogesh 整个具有该标识符的元素 - mathinvalidnik
https://dev59.com/i9nvs4cB2Jgan1zn-El6?noredirect=1#comment55983011_34115181 - CodeMan
6个回答

15
你正在调用方法 Pull(string name, MongoDB.Bson.BsonValue value),根据文档它会:

从指定数组元素中删除所有等于某个值的数据(参见 $pull)。

而你提供的值是 { "Identifier", productId }。我猜MongoDB没有找到 完全一样 的值。
尝试使用第二种重载的 Pull,并使用查询条件代替精确值:

从指定数组元素中删除所有满足一些查询条件的数据(参见 $pull)。

var update = Update.Pull("Products", Query.EQ("Identifier", productId));

更新

由于您提到了Category实体,因此我建议使用lambda而不是Query.EQ

var pull = Update<Category>.Pull(x => x.Products, builder =>
builder.Where(q => q.Identifier == productId));

Update<Category> 嗯,你没有提到你有 Category 类型... 无论如何,这是我的解决方案的 强类型 情况,请不要忘记标记答案。 - neleus

10

使用 C# MongoDB 驱动程序的解决方案。删除单个嵌套元素。

var filter = Builders<YourModel>.Filter.Where(ym => ym.Id == ymId);
var update = Builders<YourModel>.Update.PullFilter(ym => ym.NestedItems, Builders<NestedModel>.Filter.Where(nm => nm.Id == nestedItemId));
_repository.Update(filter, update);

1
谢谢,我已经尝试了两天才做到这个。 - Roman Sterlin
在PullFilter的第二个参数中使用Builder是必要的吗?Lambda会自动推断NestedModel类型,所以可以使用nm => nm.Id == nestedItemId代替Builders<NestedModel>.Filter ... - user10706046

3

我也遇到了同样的问题,经过大量研究和开发后,我知道了,在使用过滤器删除时,必须使用PullFilter而不是Pull。


3

我曾经遇到过从嵌套数组中删除元素的问题,但是经过研究,我找到了这段有效的代码。

var update = Builders<Category>.Update.PullFilter(y => y.Products, builder => builder.Identifier== productId);
var result = await _context.Category.UpdateOneAsync(filter, update);
return result.IsAcknowledged && result.ModifiedCount > 0;

0

你好,根据我的理解,你想要删除给定id和标识符的所有匹配元素,因此下面的查询将解决你的问题,但我不知道如何将其转换为C#,这里使用了mongo $pull方法。

db.collectionName.update({"_id" : ObjectId("55f354533dd61e5004ca5208")}, {"$pull":{"Products":{"Identifier":"170220151653"}}})

是的,我检查过了。它对我没有用。我需要C#驱动程序代码。但还是谢谢 :) - mathinvalidnik

0
C# MongoDB驱动程序的解决方案。您可以将嵌套数组设置为空[]
var filter = Builders<MyUser>.Filter.Where(mu => mu.Id == "my user id");
var update = Builders<MyUser>.Update.Set(mu => mu.Phones, new List<Phone>());
_repository.Update(filter, update);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接