如何从数组中删除单个元素

时间:2019-02-06 08:54:51

标签: c# mongodb mongodb-.net-driver

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

我有这样的文件:

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

我想从“ someArray”中删除“ IsReadOnly”字段,而不管该值是true还是false。

在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”未被删除。如何从每个数组和每个文档中删除此字段?

4 个答案:

答案 0 :(得分:1)

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

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

但是,C#驱动程序中的Builders是强类型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版本。如果您运行的是旧版本,则此方法将不起作用,因为早期版本中不存在<form method="post"> <select name="days"> <option value="2">2 days</option> <option value="3">3 days</option> </select> <select name="persons"> <option value="2">2 persons</option> <option value="4">4 persons</option> <option value="6">6 persons</option> <option value="8">8 persons</option> </select> </form> 运算符。

答案 1 :(得分:0)

嗨,您是否尝试过使用MongoDb.Driver.Linq ..进行以下操作:

var myEntity = myDb.Collection.AsQueryable().Where(xx=> xx.MyProp == somthing).FirstOrDefault(); //<-- to Extract your entity with Array Inside

然后..

var myArray = myEntity.ArrayNested.Where(xx=> xx.prop != conditiontoMatchElement).ToList();

然后..在实体内重置新数组(不包含元素)。

myentity.ArrayNested = myArray;

..然后更新它...

var result = myDb.Collection.ReplaceOne(x => x.Id.Equals(myentity.Id), myentity, new UpdateOptions
            {
                IsUpsert = false
            });

希望它对您有帮助!..

P.S。如果您未嵌套Array,则可以执行相同操作,但无需在父实体中进行设置

答案 2 :(得分:0)

在MongoDB中,您可以使用以下脚本进行访问:

db.getCollection('Collection').find({},{'someArray.IsReadOnly':0})

关键点是{'someArray.IsReadOnly':0}-find()方法的投影参数。

在此处了解有关find()的信息-https://docs.mongodb.com/manual/reference/method/db.collection.find/index.html

答案 3 :(得分:0)

以下是使用我的库MongoDB.Entities以强类型方式进行操作的方法。它使用ElemMatchUnset定义构建器方法的帮助。

using MongoDB.Entities;

namespace StackOverflow
{
    public class Program
    {
        public class User : Entity
        {
            public string Name { get; set; }
            public Post[] Posts { get; set; }
        }

        public class Post : Entity
        {
            public string Title { get; set; }
            public bool IsReadOnly { get; set; }
        }

        static void Main(string[] args)
        {
            new DB("test");

            var posts = new[] {
                new Post{ Title= "first post", IsReadOnly= true},
                new Post {Title = "second post", IsReadOnly = false}
            };
            posts.Save();

            (new User
            {
                Name = "Test User",
                Posts = posts
            }).Save();

            DB.Update<User>()
              .Match(f => f.ElemMatch(u => u.Posts, p => p.IsReadOnly == true || p.IsReadOnly == false))
              .Modify(d => d.Unset(u => u.Posts[-1].IsReadOnly))
              .Execute();
        }
    }
}

以下更新命令发送到mongodb:

db.User.update(
    {
        "Posts": {
            "$elemMatch": {
                "$or": [
                    {
                        "IsReadOnly": true
                    },
                    {
                        "IsReadOnly": false
                    }
                ]
            }
        }
    },
    {
        "$unset": {
            "Posts.$.IsReadOnly": NumberInt("1")
        }
    }
)