首页 > 解决方案 > 如何从数组中删除单个元素

问题描述

我想使用 C# 的 MongoDB 驱动程序从每个文档中删除一个字段。

我有这样的文件:

{
  "_id": ObjectId("554e05dfc90d3d4dfcaa2aea"),
  "username": "abc",
  "someArray": [
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "IsReadOnly": false
    },
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "IsReadOnly": true
    }
  ]
} 

我想从“someArray”中删除字段“IsReadOnly”,无论该值是真还是假。

在 MongoDB 中,我可以使用以下脚本来实现:

db.getCollection('Collection').find({}).forEach( function(doc) {
  var arr = doc.someArray;
  var length = arr.length;
  for (var i = 0; i < length; i++) {
    delete arr[i]["IsReadOnly"];
  }
  db.getCollection('Collection').save(doc);
});

在 C# 中,我尝试了以下操作:

var update= Update.Pull("someArray",BsonValue.Create("IsReadOnly"));

// or: var update = Update.Unset("someArray.$[].IsReadOnly");
myDb.Collection.Update(null, update, UpdateFlags.Multi);

但是“IsReadOnly”没有被删除。如何从每个数组和每个文档中删除此字段?

标签: c#mongodbmongodb-.net-driver

解决方案


在 Mongo 查询语言中,表达此更新的最简单方法是使用$[](Positional All) 运算符。它看起来像这样:

db.col.update({},{$unset:{"someArray.$[].IsReadOnly":1}},{multi:true})

但是,此运算符尚未Builders在 C# 驱动程序中可用的强类型中显式实现。

由于缺少此运算符,您必须“手动”构建更新。这是一个快速示例。

var mongo = new MongoClient();
var db = mongo.GetDatabase("test");
var col = db.GetCollection<BsonDocument>("col");
await col.UpdateManyAsync(new BsonDocument(), Builders<BsonDocument>.Update.Unset("someArray.$[].IsReadOnly"));

如果您有一些自定义序列化设置(例如较低的驼峰式字段名称),则字段命名存在一些潜在的缺陷,因此请务必进行测试。

值得注意的是,这个答案取决于您运行 3.6 或更高版本的 MongoDB。如果您运行的是旧版本,则此方法将不起作用,因为该$[]运算符在早期版本中不存在。


推荐阅读