C # MongoDb условно обновляет существующие элементы массива в документе и добавляет новый элемент - PullRequest
1 голос
/ 26 сентября 2019

Со следующей структурой документа

public class Disclaimer
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public ObjectId Id { get; set; }

    public List<Override> Overrides { get; set; }
}

public class Override
{
    public int CategoryId { get; set; }
    public DateTime EffectiveDate { get; set; }
    public DateTime? ExpiryDate { get; set; }
    public string Message { get; set; }
}

И запросом

var idFilter = Builders<Models.Database.Disclaimer>.Filter.Where(x => x.Id == ObjectId.Parse(id) && x.Overrides.Any(y => y.CategoryId == createOverrideDto.CategoryId)));

var overrideCancellations = Builders<Models.Database.Disclaimer>.Update.Set(x => x.Overrides[-1].ExpiryDate, DateTime.Now);

var update = overrideCancellations.Push(x => x.Overrides, new Models.Database.Override()
  {
    CategoryId = createOverrideDto.CategoryId,
    EffectiveDate = DateTime.Now,
    Message = createOverrideDto.Message
  });

result = _repository.Get().UpdateOne(filter, update);

Я хотел бы обновить существующие элементы переопределения с датой истечения срока действия, когда новый добавляется в тот же элементкатегории, и добавьте новый элемент.Если существуют элементы, не относящиеся к той же категории, их следует оставить в покое, просто добавьте новый элемент.

Мой текущий код работает нормально, если есть один или несколько существующих элементов Override с выбранной категорией.Однако, когда их нет, т. Е. Если массив пуст или все существующие не находятся в категории, предложение фильтра не совпадает, и обновление не выполняется.

Я пытался изменить свой фильтр, чтобы соответствовать, когдав этой категории нет переопределений.Однако затем все существующие элементы, не входящие в выбранную категорию, также обновляются, т. Е. Добавляется дата истечения срока действия.

Я мог бы изменить структуру своего документа так, чтобы переопределением был объект с полем идентификатора категории, а затем отдельные массивы, но яможет все еще иметь проблему upsert?

1 Ответ

1 голос
/ 28 сентября 2019

, что вы хотите сделать, требует использования фильтров массива и массового обновления с 2 шагами.Вот пример того, как это делается с использованием MongoDB.Entities для краткости.но он напрямую переводится официальному водителю, так как это просто оболочка для водителя.

using MongoDB.Entities;
using System;

namespace StackOverflow
{
    public class Disclaimer : Entity
    {
        public Override[] Overrides { get; set; }
    }

    public class Override
    {
        public int CategoryId { get; set; }
        public DateTime EffectiveDate { get; set; }
        public DateTime? ExpiryDate { get; set; }
        public string Message { get; set; }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            new DB("test", "localhost");

            // create seed data
            var seed = new Disclaimer
            {
                Overrides = new[]
                {
                    new Override
                    {
                        CategoryId = 666, EffectiveDate = DateTime.Now.AddDays(-1), Message = "disclaimer 1"
                    },
                    new Override
                    {
                        CategoryId = 666, EffectiveDate = DateTime.Now.AddDays(-1), Message = "disclaimer 2"
                    },
                    new Override
                    {
                        CategoryId = 777, EffectiveDate = DateTime.Now.AddDays(-1), Message = "disclaimer 3"
                    }
                }
            }; seed.Save();

            // start bulk update command
            DB.Update<Disclaimer>()

              // step1: set expiry date on existing 666s
              .Match(d => d.ID == seed.ID)
              .WithArrayFilter("{ 'x.CategoryId' : 666 }")
              .Modify(b => b.Set("Overrides.$[x].ExpiryDate", DateTime.Now))
              .AddToQueue()

              // step2: add a new 666
              .Match(d => d.ID == seed.ID)
              .Modify(b => b.Push(d => d.Overrides,
                                         new Override
                                         {
                                             CategoryId = 666,
                                             EffectiveDate = DateTime.Now,
                                             Message = "disclaimer 4"
                                         }))
              .AddToQueue()

              // run two step bulk update command
              .Execute();
        }
    }
}
...