【发布时间】:2017-01-14 12:39:25
【问题描述】:
对于 MongoDB,当我进行不匹配任何文档的更新时,更新返回它没有更新任何文档,但仍然创建了一个文档
代码如下:
public class MyObject
{
[BsonIgnoreIfDefault]
public string _id { get; set; }
public int X { get; set; }
}
static void Main(string[] args)
{
var Client = new MongoClient("mongodb://localhost");
var Database = Client.GetDatabase("testdatabase");
var Driver = Database.GetCollection<MyObject>("testcollection");
Driver.Indexes.CreateOne(Builders<MyObject>.IndexKeys.Ascending(_ => _._id));
var C1 = Driver.Count(_ => true);
// c1 == 0 since the db is empty
var A1 = Driver.UpdateMany(_ => false, Builders<MyObject>.Update.Set(_ => _.X, 1), new UpdateOptions {IsUpsert = true});
//A1.MatchedCount == 0
//A1.ModifiedCount == 0;
//A1.Upsertdld = (some id)
var C2 = Driver.Count(_ => true);
// c2 == 1 because a dummy document was created due to the upsert flag
var A2 = Driver.UpdateMany(_ => true, Builders<MyObject>.Update.Set(_ => _.X, 3), new UpdateOptions {IsUpsert = true});
//A2.MatchedCount == 1
//A2.ModifiedCount == 1;
//A2.Upsertdld = null;
var C3 = Driver.Count(_ => true);
// c3 == 1 since no new dummy documents were created as there was a match
}
看起来 Upsert 标志是罪魁祸首,但我不明白为什么它凭空创建一个文档,因为没有什么可更新的。 (在第二次调用时,它有一个匹配并且不会创建一个虚拟对象。)
【问题讨论】:
-
Upsert 行为是在不匹配时插入文档,在匹配时更新文档。似乎这就是正在发生的事情。你期待别的吗? docs.mongodb.com/manual/reference/method/db.collection.update
-
我预计它的行为会有所不同:我将字符串作为 _id(它们本质上是 microsoft 格式的 guid),它是 MyObject 类型的一部分。但是当更新确实更新了一个空文档时,它会创建一个以 ObjectId 作为 _id 类型的记录;那么所有后续调用都会失败,因为无法将记录反序列化为我创建的类型。
-
是否有办法强制创建 _id 本质上是默认值的记录(typeof(_id))?在这种情况下默认(字符串)?
-
您可以尝试将
_id包含在查询条件中,以便使用指定的 id 创建更新插入条目,或者其他选项将插入与更新分开,这意味着更新插入标志为假。跨度>