【问题标题】:Mongo C# - Update behavior, creating dummy record when no matchMongo C# - 更新行为,在不匹配时创建虚拟记录
【发布时间】: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 创建更新插入条目,或者其他选项将插入与更新分开,这意味着更新插入标志为假。跨度>

标签: c# mongodb


【解决方案1】:

当您使用IsUpsert = true 时,您调用 MongoDB C# 驱动程序来查找至少一个文档以更新或插入新文档。
当您的集合为空时,将执行插入命令;像这样:

//var A1 = Driver.UpdateMany(_ => false, Builders<MyObject>.Update.Set(_ => _.X, 1), new UpdateOptions {IsUpsert = true});

var A1 = Driver.InsertOne(new MyObject { X = 1 });

据记载:

如果文档没有指定_id字段,那么MongoDB会在插入之前添加_id字段并为文档分配一个唯一的ObjectId。大多数驱动程序创建一个ObjectId 并插入_id 字段,但如果驱动程序或应用程序没有,mongod 将创建并填充_id

在较新版本的 C# MongoDB 驱动程序中,您可以使用 Builders&lt;MyObject&gt;.Filter.Empty 而不是推荐的 _ =&gt; true

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多