简体   繁体   English

在Mongodb .Net驱动程序中应用upsert

[英]Applying upsert in Mongodb .Net driver

I need to perform atomic "if not exist add" logic, else do nothing, to do this I am using Upsert. 我需要执行原子的“如果不存在添加”逻辑,否则什么也不做,为此我正在使用Upsert。

My model: 我的模特:

  public class Person
  {
    [BsonId]
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Title { get; set; }
    public DateTime ReceivedAt { get; set; }
    public List<Person> Children { get; set; }
  }

my code: 我的代码:

var person = new Person() { Id = Guid.NewGuid(), Name = "name", Title = "title", ReceivedAt = DateTime.Now };
var result = context.People.FindOneAndUpdateAsync<Person>(
           x => x.Title == person.Title && x.Name == person.Name && x.ReceivedAt <= person.ReceivedAt + TimeSpan.FromMinutes(1),
           Builders<Person>.Update.Combine(),
           new FindOneAndUpdateOptions<Person>() { IsUpsert = true });

The above is not inserting the document is not exist, what I am doing wrong? 上面没有插入的文件不存在,我在做什么错? do I need to set something other than IsUpsert? 我是否需要设置IsUpsert以外的其他内容?

In your code result is of type Task<Person> and you miss await here and that's why you don't observe that Exception is thrown. 在您的代码中, result的类型为Task<Person> ,您await这里错过了await ,这就是为什么您没有观察到抛出Exception的原因。 When you change your code to: 当您将代码更改为:

var result = col.FindOneAndUpdateAsync<Person>(
                   x => x.Title == person.Title && x.Name == person.Name && x.ReceivedAt <= person.ReceivedAt + TimeSpan.FromMinutes(1),
                   Builders<Person>.Update.Combine(),
                   new FindOneAndUpdateOptions<Person>() { IsUpsert = true })
               .GetAwaiter().GetResult(); // or await in front of invocation

You'll get an ArgumentException with following message: 您将收到带有以下消息的ArgumentException

Additional information: Updates must have at least 1 update operator. 附加信息:更新必须至少具有1个更新运算符。

So you can't have empty update. 因此,您不能有空更新。 To fix that you can for instance repeat Title property, which works exactly the same way as your code expects. 要解决此问题,您可以例如重复Title属性,该属性的工作原理与代码预期的完全相同。

var result = col.FindOneAndUpdateAsync<Person>(
                   x => x.Title == person.Title && x.Name == person.Name && x.ReceivedAt <= person.ReceivedAt + TimeSpan.FromMinutes(1),
                   Builders<Person>.Update.Set(x => x.Title, person.Title),
                   new FindOneAndUpdateOptions<Person>() { IsUpsert = true }).GetAwaiter().GetResult();

ReceivedAt will not be added since your lambda expression translates to $lte which is not an equality comparison (check docs here ). 由于您的lambda表达式会转换为$lte ,而不是相等比较,因此不会添加ReceivedAt (请在此处检查文档)。 You should explicitly define that value in update part. 您应该在更新部分中明确定义该值。

The update creates a base document from the equality clauses in the parameter, and then applies the update expressions from the parameter. 此更新根据参数中的相等性子句创建基础文档,然后应用参数中的更新表达式。 Comparison operations from the will not be included in the new document. 来自的比较操作将不会包含在新文档中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM