我有一个数据,比如一个文档中的5个字段,假设这3个字段这3个字段唯一地帮助识别文档.

Name:A, Type: B, Contact: C

我希望避免在文档中为这些字段重复输入(插入).我现在正在使用以下代码

_mongoCollection.GetCollection<ModelClass>('collectionName').Find(s => s.Name==A && s.Type==B && s.Contact==C).FirstORDefault();

如果结果为空;我们插入使用:

_mongoCollection.getCollection<BsonDocument>('collectionName');

然后使用InsertOne插入.有没有更好的方法来实现这一点并避免重复?

推荐答案

您可以使用Upsert进行此操作:

var coll = _mongoCollection.getCollection<ModelClass>("collectionName");
var model = new ModelClass() 
{
  Name = A, 
  Type = B, 
  Contact = C, 
  Field4 = "F4", 
  Field5 = "F5",
};
await coll.ReplaceOneAsync(s => s.Name == model.Name 
  && s.Type == model.Type 
  && s.Contact == model.Contact, 
  model, 
  new ReplaceOptions() { IsUpsert = true });

上述代码判断是否存在匹配的文档;如果是,则将其替换,否则将插入新文档.如果方法不是asyncUpdateOne(Async),也可以使用ReplaceOne来更细粒度地更新现有文档.

更新后插入

例如,如果只想在没有文档的情况下插入新文档,可以使用以下不替换文档的upsert:

var coll = _mongoCollection.getCollection<ModelClass>("collectionName");
var model = new ModelClass() 
{
  Name = A, 
  Type = B, 
  Contact = C, 
  Field4 = "F4", 
  Field5 = "F5",
};
var update = Builders<ModelClass>.Update
  .SetOnInsert(x => x.Field4, model.Field4)
  .SetOnInsert(x => x.Field5, model.Field5);
var result = await coll.UpdateOneAsync(
  x => x.Name == model.Name && x.Type == model.Type && x.Contact == model.Contact, 
  update, 
  new UpdateOptions() { IsUpsert = true });

如果还不存在任何文档,则上述代码将创建一个新文档.如果插入了文档,则可以选中result.UpsertedId.如果为空,则表示未插入任何文档,否则它包含插入文档的id.

更新仅对其余两个字段使用SetOnInsert个操作.如果文档已存在,则保持不变.

批量升级并更新

如果要使用批量操作执行多个upserts,可以使用以下代码:

var update = Builders<ModelClass>.Update
    .SetOnInsert(x => x.Field4, model.Field4)
    .SetOnInsert(x => x.Field5, model.Field5);
var bldr = Builders<ModelClass>.Filter;
var updates = new List<WriteModel<ModelClass>>();
var updateOneModel = new UpdateOneModel<ModelClass>(
    bldr.Eq(x => x.Name, model.Name) & bldr.Eq(x => x.Type, model.Type) & bldr.Eq(x => x.Contact, model.Contact), 
    update);
updateOneModel.IsUpsert = true;
updates.Add(updateOneModel);
// ... add additional UpdateModels
var result = await coll.BulkWriteAsync(updates);

在这种情况下,result包含一个upserted id的列表;还有一个Index属性,您可以使用它来找出哪些UpdateModels导致了向上插入,哪些没有.

Csharp相关问答推荐

下拉图片点击MudBlazor

获取ASP.NET核心身份认证cookie名称

如何告诉自己创建的NuGet包在应用程序中发生了变化?

迭代C#List并在数据库中 for each 元素执行SELECT语句—更有效的方式?

如何注册实现同一接口的多个服务并注入到控制器构造函数中

将轮询与超时同步

使用Orleans进行的单元测试找不到接口的实现

TCPClient阅读流

使用Entity Framework6在对象中填充列表会导致列表大多为空

数据库.Migrate在对接容器重启时失败

在扩展方法中,IEnumerable<;T>;不会转换为IEumerable<;T&>

如何强制新设置在Unity中工作?

这是否比决定是否使用ConfigureAWait(False)更好?

如何使用实体框架核心对字符串_agg使用强制转换为varchar(Max)

为什么在使用JsonDerivedType序列化泛型时缺少$type?

C#USB条形码 scanner 在第二次扫描时未写入行尾字符

有没有更好的方法来使用LINQ获取整行的计算组

如何根据分割文本的块数来计算文本的大小?

System.Net.Http.HttpClient返回错误&Quot;Err:缺少UA30&Quot;

Firefox中的MudBlazor DataGrid单元格溢出