C# MongoDb 有条件地更新文档中的现有数组元素并添加新元素
C# MongoDb Conditionally Update Existing Array Elements In Document And Add New Element
具有以下文档结构
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 元素,我当前的代码可以正常工作。但是,如果没有,即如果数组为空或所有现有的都不在类别中,则过滤子句不匹配,并且不会运行更新。
我已尝试修改我的过滤器以匹配此类别中没有覆盖的情况。但是,不在所选类别中的任何现有元素也会更新,即添加到期日期。
我可以更改我的文档结构,以便 Overrides 是一个具有类别 ID 字段的对象,然后是单独的数组,但我可能仍然遇到更新插入问题?
您要执行的操作需要使用数组过滤器和 2 个步骤的批量更新。为了简洁起见,这里有一个如何使用 MongoDB.Entities 完成的示例。但它可以直接翻译成官方驱动程序,因为它只是驱动程序的包装器。
using MongoDB.Entities;
using System;
namespace Whosebug
{
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();
}
}
}
具有以下文档结构
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 元素,我当前的代码可以正常工作。但是,如果没有,即如果数组为空或所有现有的都不在类别中,则过滤子句不匹配,并且不会运行更新。
我已尝试修改我的过滤器以匹配此类别中没有覆盖的情况。但是,不在所选类别中的任何现有元素也会更新,即添加到期日期。
我可以更改我的文档结构,以便 Overrides 是一个具有类别 ID 字段的对象,然后是单独的数组,但我可能仍然遇到更新插入问题?
您要执行的操作需要使用数组过滤器和 2 个步骤的批量更新。为了简洁起见,这里有一个如何使用 MongoDB.Entities 完成的示例。但它可以直接翻译成官方驱动程序,因为它只是驱动程序的包装器。
using MongoDB.Entities;
using System;
namespace Whosebug
{
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();
}
}
}