我有一个需要经常更新的集合。结构如下:
{
ObjectId _Id;
string EntryKey;
string Description;
string SearchTerm;
}
在EntryKey
字段上有一个唯一的索引,我创建如下upsert操作:
var filter = filterBuilder.Eq(e => e.EntryKey, model.EntryKey);
var update = updateBuilder.Combine(
updateBuilder.SetOnInsert(e => e._Id, ObjectId.GenerateNewId()),
updateBuilder.SetOnInsert(e => e.EntryKey, model.EntryKey.ToLower()),
updateBuilder.Set(e => e.Description, model.Description),
updateBuilder.Set(e => e.SearchTerm, model.SearchTerm));
var op = new UpdateOneModel<SearchEntry>(filter, update){ IsUpsert = true, Hint = "EntryKey_1" };
bulkList.Add(op);
在每个测试中使用完全相同的输入数据和新的mongo示例,第一次迭代成功,第二次迭代失败,EntryKey字段为E10000: duplicate key error collection
当我从索引中删除唯一约束时,集合中会创建重复的文档(_Id
除外)
当我使用相同的失败ID在shell中运行命令时,命令成功并且文档被更新。
db.search.bulkWrite([
{
updateOne: {
"filter": { "EntryKey": "ad544f72-496f-4eee-bf53-ffdda57de824" },
"update": {
$setOnInsert: {
_id: ObjectId(),
"EntryKey": "ad544f72-496f-4eee-bf53-ffdda57de824"
},
$set: {
"Description": "This is a description",
"SearchTerm",: "search"
}
},
"upsert": true
}
}
]);
我希望与过滤器 predicate 匹配的文档得到更新,而不是抛出重复键错误(当强制使用唯一索引时)或插入本质上重复的文档。
我在this问题中看到,可接受的答案是将更新与插入分开。如果是这样的话,那么如果不能以这里尝试的方式使用upsert,那么它的意义何在?
1条答案
按热度按时间xqk2d5yq1#
当代码第一次运行时,它将创建一个文档,其中
EntryKey
设置为model.EntryKey.ToLower()
。在第二次运行中,将
EntryKey
与model.EntryKey
进行比较,因为在upsert中它是小写的,所以只有在model.EntryKey
中没有大写字母时才匹配。如果有,过滤器将无法匹配,并将尝试upsert,但在转换为小写后失败。
为了保持一致性,还要在筛选器中使用小写,如