MongoDb C # проблемы параллелизма с upsert - PullRequest
1 голос
/ 20 мая 2019

У меня есть довольно простой метод для добавления записи в коллекцию:

    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
        });
    }

Коллекция имеет уникальный индекс для Key.

Я вызываю метод UpsertEntry вПараллельно. Для цикла

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

Я бы ожидал вставить 100 записей, но вместо этого я получил E11000 duplicate key error collection: TestDB.test::c7 index: key_1 dup key: { : "key+1" }.Почему у меня возникают проблемы с параллелизмом?Что не так с моим кодом?

Ответы [ 2 ]

0 голосов
/ 21 мая 2019

Я решил, и это не имеет никакого отношения к самому драйверу. Я не заметил, что я снова использую тот же экземпляр класса Entry: -)

0 голосов
/ 20 мая 2019

В сообщении об ошибке говорится, что запись с нулевым значением уже существует. Другими словами, это означает, что у вас уже есть один с тем же ключом, представленным в коллекции

Соответствующая документация для этого:

Если документ не имеет значения для индексированного поля в уникальном index, индекс будет хранить нулевое значение для этого документа. Потому что уникальное ограничение, MongoDB будет разрешать только один документ, который не хватает индексированного поля. Если существует более одного документа без значение для индексированного поля или отсутствует индексированное поле, индекс сборка завершится с ошибкой дубликата ключа.

Вы можете объединить уникальное ограничение с разреженным индексом для фильтрации эти нулевые значения из уникального индекса и избежать ошибки.

уникальные индексы

Разреженные индексы содержат записи только для документов, имеющих индексированное поле, даже если

поле индекса содержит нулевое значение.

Другими словами, разреженный индекс подходит для нескольких документов со всеми нулевыми значениями.

...