MongoError: коллекция ошибок повторяющихся ключей E11000 для уникального составного индекса

Вопрос связан с индексом unique compound, в отличие от других подобных вопросов, которые имеют только индекс unique. У меня также есть sparse: true для индексов.

У меня есть следующие индексы в моей коллекции

[
  {
    "v": 2,
    "key": {
      "_id": 1
    },
    "name": "_id_",
    "ns": "somedb.votes"
  },
  {
    "v": 2,
    "key": {
      "answerId": 1
    },
    "name": "answerId_1",
    "ns": "somedb.votes",
    "sparse": true,
    "background": true
  },
  {
    "v": 2,
    "key": {
      "questionId": 1
    },
    "name": "questionId_1",
    "ns": "somedb.votes",
    "sparse": true,
    "background": true
  },
  {
    "v": 2,
    "unique": true,
    "key": {
      "answerId": 1,
      "votedBy": 1
    },
    "name": "answerId_1_votedBy_1",
    "ns": "somedb.votes",
    "sparse": true,
    "background": true
  },
  {
    "v": 2,
    "unique": true,
    "key": {
      "questionId": 1,
      "votedBy": 1
    },
    "name": "questionId_1_votedBy_1",
    "ns": "somedb.votes",
    "sparse": true,
    "background": true
  }
]

и у меня есть следующий документ в коллекции

{
  "_id": ObjectId("59fdd3ce915511329553dfaa"),
  "updatedAt": ISODate("2017-11-04T14:54:22.110Z"),
  "votedAt": ISODate("2017-11-04T14:50:54.681Z"),
  "questionId": ObjectId("59fc77e45a857465a90339cc"),
  "value": -1,
  "votedBy": ObjectId("59fc4274aa686d39abe5d58a"),
  "type": "QuestionVote",
  "__v": 0
}

Теперь, когда я пытаюсь выполнить следующее

db.votes.insert({ questionId: ObjectId("59fc798d5a857465a90339cf"), value: -1, votedBy: ObjectId("59fc4274aa686d39abe5d58a"), type: 'QuestionVote', _id: ObjectId("5a003240bfd8194a02d0add8") })

Я получаю следующую ошибку

E11000 duplicate key error collection: somedb.votes index: answerId_1_votedBy_1 dup key: { : null, : ObjectId('59fc4274aa686d39abe5d58a') }
WriteResult({
  "nInserted": 0,
  "writeError": {
    "code": 11000,
    "errmsg": "E11000 duplicate key error collection: somedb.votes index: answerId_1_votedBy_1 dup key: { : null, : ObjectId('59fc4274aa686d39abe5d58a') }"
  }
})

Я не понимаю причины. Индексы sparse и compound. Но ошибка как раз из-за наличия того же поля votedBy.

то есть выполнение следующего,

db.votes.insert({votedBy: ObjectId("59fc4274aa686d39abe5d58a")})

Я получаю следующую ошибку, даже если для объекта votedBy нет явного индексирования.

E11000 duplicate key error collection: somedb.votes index: answerId_1_votedBy_1 dup key: { : null, : ObjectId('59fc4274aa686d39abe5d58a') }
WriteResult({
  "nInserted": 0,
  "writeError": {
    "code": 11000,
    "errmsg": "E11000 duplicate key error collection: somedb.votes index: answerId_1_votedBy_1 dup key: { : null, : ObjectId('59fc4274aa686d39abe5d58a') }"
  }
})

Ссылка: составной индекс — https://docs.mongodb.com/manual/core/index-compound/#compound-indexes


person abhisekp    schedule 06.11.2017    source источник
comment
Потому что, как и все вопросы, которые уже были заданы ранее, answerId_1_votedBy_1 dup key: { : null, указывает на то, что ваш answerId не был указан в каждом отдельном документе и, следовательно, имеет null, который вы просили сделать уникальным. Даже в составном вы можете иметь только один. То, что вы делаете точно так же, как и все остальные вопросы, — это добавление фильтра разреженного или частичного индекса в современных версиях для обслуживания документов, в которые вы не добавили это значение, которое является частью составного индекса.   -  person Neil Lunn    schedule 06.11.2017
comment
@NeilLunn Я добавил sparse. Но все же я получаю эту ошибку. Вы можете увидеть список индексов. sparse: true присутствует.   -  person abhisekp    schedule 06.11.2017
comment
Таким образом, вся причина, по которой это вас раздражает, заключается в том, что вы перекрываете поле votedBy с двумя другими ключами, которые могут составить соединение. По сути, это означает, что один пользователь получает 1 голос за ответ, 1 голос за вопрос и 1 голос, который на самом деле не назначен ни одному из них. Это то, что вы применяете здесь и, похоже, не понимаете этого. Вместо этого вам нужно "_id", "type", "voted_by", где есть один уникальный индекс, и вы различаете значение типа, а не имя поля answerId/questionId. Это фиксированное наименование и чередование и является причиной проблемы.   -  person Neil Lunn    schedule 06.11.2017
comment
@NeilLunn Но я не могу иметь _id как questionId или answerId, так как могут быть одинаковые questionId с разными votedBy. Что мне делать и как структурировать?   -  person abhisekp    schedule 06.11.2017
comment
Я не имею в виду буквально первичный ключ _id. Просто используйте одно поле для этого значения, а не два.   -  person Neil Lunn    schedule 06.11.2017


Ответы (2)


Возможно, это связано с наличием старых индексов в той же коллекции, что и при проверке из консоли с помощью этого метода:

db.votes.getIndexes()

Затем бросьте их:

db.votes.dropIndexes()

В вашем приложении, где вы определяете свою схему, вы должны индексировать составной индекс следующим образом:

<your_schema_name>.index({
  field1: 1,
  field2:1,
  etc...
},{
    unique: true,
    sparse: true  //N.B:(sparse:true) is not a must for the compound unique indexing to work
});

Теперь перезапустите приложение, и последнее окончательное желаемое составное индексирование должно работать.

Дополнительное примечание

Я обнаружил, что при создании уникальных индексов и в вашей БД уже есть записи, которые нарушают это создание, это не работает.

Из node.js:

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

Mongoose: <my_collection>.ensureIndex({ field1: 1, 'field2.xx.xxx': 1, field: 3 }, { unique: true, background: true })

и я не получил никакой ошибки от узла, но когда я проверил из консоли метод getIndexes(), я не нашел новую индексацию.

В консоли:

Я попытался обеспечить индекс

db.<my_collection>.ensureIndex({ field1: 1, 'field2.xx.xxx': 1, field: 3 }, { unique: true, background: true })

Я получил ошибку с записью, которая нарушает эту индексацию

{
    "ok" : 0,
    "errmsg" : "E11000 duplicate key error collection: <db_name>.<collection_name> index: field1_xxx.xxxx.xxxx_1_filed2_1 dup key: { : \"xxx\", : \"xxxx\", : ObjectId('xxx') }",
    "code" : 11000
}

Заключение

Уникальная индексация (составная или нет) не будет работать, если есть какая-либо запись, которая нарушает новую желаемую индексацию, даже если вы удалите все свои индексы и повторите попытку переиндексации, как я упоминал ранее.

person Farouk El kholy    schedule 08.11.2017
comment
Я сбросил коллекцию и воссоздал ее. Но проблема в том, как указал @NeilLunn в комментариях к вопросу. И решение состоит в том, чтобы создать одно и то же поле для обеих схем и проиндексировать их, а не иметь два разных поля. - person abhisekp; 10.11.2017

Причина этой ошибки в том. Индекс отсутствует в вашей коллекции, в которую вы пытаетесь вставить запись. Итак, решение: отбросьте эту коллекцию и снова запустите свою программу.

person user2049674    schedule 14.03.2020
comment
Вам нужно добавить новое соединение перед повторным запуском? - person Nelles; 14.03.2020