MongoDB - Почему индекс _id не выдает ошибку для дублированных записей?

Я совершенно новичок в базах данных NoSQL, и сейчас я работаю с MongoDB.

Я пытаюсь понять, почему по умолчанию _id Индекс не выдает ошибку, когда upserting a duplicate _id документ.

Как указано в документации _id является уникальным индексом по умолчанию

(хотя здесь не показан уникальный флаг..)

> db.foo.getIndexes();
[
    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.foo"
    }
]
>

Так когда upserting документ (начался с пустой коллекции),
если сначала вставить его, а затем, кажется, "игнорировать" его.

> db.foo.update({ _id: 'doe123'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : "doe123" })

> db.foo.update({ _id: 'doe123'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

Так что я попробовал другую вещь и создал unique index на "имя".

Результат сохранения дублирующего имени:

> db.foo.update({ _id: 'foo456'}, { _id: 'foo456', name: 'John Doe'}, { upsert: true});
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "E11000 duplicate key error collection: test.foo index: name_1 dup key: { : \"John Doe\" }"
    }
})

Почему я не получаю такую ​​ошибку на дубликате? _id?


РЕДАКТИРОВАТЬ: я использую MongoDB v.3.2.3

1 ответ

Решение

Нет причины показывать ошибку дублируемого индекса в первом случае, так как он просто пытается обновить _id а также name поля одной и той же записи с одинаковым значением.

Если вы попробуете

  db.foo.update({ _id: '1098'}, { _id: 'doe123', name: 'John Doe'}, { upsert: true});

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

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

Редактировать:-

Если вы пытаетесь

 db.foo.insert({ _id: 'doe123', name: 'John Doe'});

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

upsert:true: - если upsert равен true и ни один документ не соответствует критериям запроса, update() вставляет один документ.

Если upsert равен true и существуют документы, соответствующие критериям запроса, update() выполняет обновление.

Другие вопросы по тегам