Как удалить один элемент из массива - PullRequest
0 голосов
/ 06 февраля 2019

Я хочу удалить одно поле из каждого документа, используя драйвер MongoDB для C #.

У меня есть такие документы:

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

Я хочу удалить поле "IsReadOnly" из "someArray ", независимо от того, является ли значение истинным или ложным.

В 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 голосов
/ 16 июня 2019

вот как это сделать строго типизированным способом, используя мою библиотеку MongoDB.Entities .он заручается поддержкой методов построения определений ElemMatch и Unset.

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")
        }
    }
)
0 голосов
/ 06 февраля 2019

В 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

0 голосов
/ 06 февраля 2019

На языке запросов 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"));

Здесь есть некоторые потенциальные подводные камни с именами полей, если у вас есть некоторые пользовательские настройки сериализации (например, имена полей в нижнем верблюжьем корпусе), поэтому обязательно проверьте вещи.

Стоит отметить, что этот ответ зависит от того, используете ли вы версию MongoDB версии 3.6 или новее.Если вы используете более старую версию, этот метод не будет работать, так как оператор $[] не существует в более ранних версиях.

0 голосов
/ 06 февраля 2019

Привет. Вы пробовали с 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
            });

Надеюсь, это поможет вам !! ..

PS.если ваш массив не является вложенным, вы можете сделать то же самое, но без установки в родительском объекте

...