具有以下文档结构
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元素时,我想用到期日期更新它,并添加新元素。如果存在不属于同一类别的现有元素,则应将其单独放置,仅应添加新元素。
如果存在一个或多个具有选定类别的现有Override元素,则我当前的代码可以正常工作。但是,如果没有,即数组为空或所有现有数组都不在类别中,则filter子句不匹配,并且不运行更新。
在此类别中没有替代项时,我尝试过修改过滤器以使其匹配。但是,所有不在选定类别中的现有元素也会被更新,即添加了过期日期。
我可以更改文档结构,以使Overrides是具有类别ID字段的对象,然后是单独的数组,但是我仍然可能遇到upsert问题?
答案 0 :(得分:1)
您要执行的操作需要使用数组过滤器和包含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();
}
}
}