简体   繁体   English

MongoDB C#并发问题与upsert

[英]MongoDb C# concurrency issues with upsert

I have a quite simple method for upserting an entry in a collection: 我有一个非常简单的方法来对集合中的条目进行增补:

    public void UpsertEntry(string collectionName, Entry entry)
    {
        var collection = GetCollection(collectionName);
        var filter = Builders<Entry>.Filter.Eq(x => x.Key, entry.Key);
        var update = Builders<Entry>.Update
            .SetOnInsert(x => x.Id, ObjectId.GenerateNewId())
            .SetOnInsert(x => x.Key, entry.Key)
            .Set(x => x.LastUpdated, DateTime.Now)
            .Set(x => x.Data, entry.Data)
            .Inc(x => x.Version, 1);

        var result = collection.UpdateOne(filter, update, new UpdateOptions
        {
            IsUpsert = true
        });
    }

The collection has a unique index on Key. 该集合在Key上具有唯一索引。

I'm calling the UpsertEntry method in a Parallel.For loop 我在Parallel.For循环中调用UpsertEntry方法

        Parallel.For(0, 100, i =>
        {
            entry.Key = $"key+{i}";
            UpsertEntry(coll, entry);
        });

I'd expect to get 100 record inserted, but instead I receive a E11000 duplicate key error collection: TestDB.test::c7 index: key_1 dup key: { : "key+1" } . 我希望插入100条记录,但是我收到一个E11000 duplicate key error collection: TestDB.test::c7 index: key_1 dup key: { : "key+1" } Why am I experiencing concurrency issues? 为什么会遇到并发问题? What's wrong with my code? 我的代码有什么问题?

The error message is saying that there's already a record with null. 错误消息是说已经有一个空记录。 In other words, it means that you already have one with the same key represented in the collection 换句话说,这意味着您已经拥有一个具有与集合中表示的相同密钥的密钥

The relevant documentation for this: 相关文档:

If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. 如果文档在唯一索引中没有索引字段的值,则索引将为此文档存储一个空值。 Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field. 由于存在独特的约束,MongoDB将只允许一个缺少索引字段的文档。 If there is more than one document without a value for the indexed field or is missing the indexed field, the index build will fail with a duplicate key error. 如果有多个文档没有索引字段的值或缺少索引字段,则索引构建将失败,并出现重复的键错误。

You can combine the unique constraint with the sparse index to filter these null values from the unique index and avoid the error. 您可以将唯一性约束与稀疏索引结合使用,以从唯一性索引中过滤这些空值并避免错误。

unique indexes 唯一索引

Sparse indexes only contain entries for documents that have the indexed field, even if 稀疏索引仅包含具有索引字段的文档条目,即使

the index field contains a null value. 索引字段包含一个空值。

In other words, a sparse index is ok with multiple documents all having null values. 换句话说,对于所有都具有空值的多个文档,可以使用稀疏索引。

I resolved it and it has nothing to do with the driver itself. 我解决了它,它与驱动程序本身无关。 I didn't noticed I was re-using the same instance of the class Entry :-) 我没有注意到我正在重用类Entry的相同实例:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM