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

问题描述 投票:0回答:4

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

我有这样的文件:

{
  "_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# mongodb mongodb-.net-driver
4个回答
1
投票

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

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

然而,this operator has not been explicitly implemented在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"));

这里有一些潜在的问题与现场的命名,如果你有一些自定义序列化设置(如降低骆驼套管字段名),所以一定要测试的东西。

值得注意的是,这个答案是偶然在你运行某个版本的MongoDB是3.6或更高版本。如果您运行的是旧版本,这个方法是行不通的$[]运营商并不在早期版本存在。


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。如果数组是没有嵌套,你可以这样做,但没有将其设置在父亲实体


0
投票

在MongoDB中可以达到与下面的脚本:

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

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

阅读关于发现()在这里 - https://docs.mongodb.com/manual/reference/method/db.collection.find/index.html


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")
        }
    }
)
© www.soinside.com 2019 - 2024. All rights reserved.