Mongo C# — поведение обновления, создание фиктивной записи при отсутствии совпадения

С 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 является виновником, но я не понимаю, почему он создает документ из воздуха, так как нет ничего, чтобы обновить.
(При втором вызове он имеет соответствие и не создает манекен.)

1 ответ

  1. При использовании IsUpsert = trueвы вызываете драйвер MongoDB C#, чтобы найти хотя бы один документ для обновления или вставки нового документа.
    Когда ваша коллекция пуста, вместо этого будет выполнена команда insert; как это:

    //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<MyObject>.Filter.Emptyвместо _ => trueрекомендованных.