E11000 индекс ошибки повторяющегося ключа в mongodb mongoose


229

Следующее - моя userсхема в user.jsмодели -

var userSchema = new mongoose.Schema({
    local: {
        name: { type: String },
        email : { type: String, require: true, unique: true },
        password: { type: String, require:true },
    },
    facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
    }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

Вот как я использую его в моем контроллере -

var user = require('./../models/user.js');

Вот как я сохраняю это в БД -

user({'local.email' : req.body.email, 'local.password' : req.body.password}).save(function(err, result){
    if(err)
        res.send(err);
    else {
        console.log(result);
        req.session.user = result;
        res.send({"code":200,"message":"Record inserted successfully"});
    }
});

Ошибка -

{"name":"MongoError","code":11000,"err":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: mydb.users.$email_1  dup key: { : null }"} 

Я проверил коллекцию БД и такой дублированной записи не существует, дайте мне знать, что я делаю неправильно?

К вашему сведению - req.body.emailи req.body.passwordвыбираем значения.

Я также проверил этот пост, но без помощи STACK LINK

Если я удалил полностью, то вставляет документ, в противном случае выдает ошибку «Дублировать», даже если у меня есть запись в local.email


1
Была такая же ошибка! Во время разработки мы отключили автоматическую индексацию и использовали строчные имена / ключи схем. Позже мы решили использовать TitleCase вместо этого, но не смогли обновить имена наших индексов (то есть: titleCase вместо TitleCase). Поэтому, когда мы включили индексирование, мы получили эту ошибку. Потребовалось немного времени, чтобы понять это. Вы хотите убедиться, что все имена / ключи названы точно везде.
Джич

6
У меня была та же ошибка, и установка модели Мангуста unique: falseне оказала никакого влияния. Я понял, что сначала должен уронить стол, а потом все заработает. Вы можете сделать что-то вроде db.whateverthecollection.drop({}). Будьте осторожны, он удаляет коллекцию.
Пере

1
_id: mongoose.Types.ObjectId, потому что требуется уникальный идентификатор
Mayank Pandav

Ответы:


241

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

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

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

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

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

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

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

разреженные индексы


Из комментариев:

Ваша ошибка говорит о том, что ключ назван, mydb.users.$email_1что заставляет меня подозревать, что у вас есть индекс для обоих users.emailи users.local.email(первый является старым и не использованным в данный момент). Удаление поля из модели Mongoose не влияет на базу данных. Проверьте, mydb.users.getIndexes()если это так, и вручную удалите нежелательный индекс с помощью mydb.users.dropIndex(<name>).


1
Я только что удалил этот пустой документ, и он сработал :) +1 .. спасибо за помощь
Trialcoder

70
Ваша ошибка говорит о том, что ключ назван, mydb.users.$email_1что заставляет меня подозревать, что у вас есть индекс для обоих users.emailи users.local.email(первый является старым и не использованным в данный момент). Удаление поля из модели Mongoose не влияет на базу данных. Проверьте, mydb.users.getIndexes()если это так, и вручную удалите нежелательный индекс с помощью mydb.users.dropIndex(<name>).
RickN

17
Или используйте, db.users.dropIndexes()если вы делаете несколько изменений индекса
cs_stackX

1
Это было проблемой для меня, когда я использовал плагин mongoose passport-local-mongoose без указания имени пользователя для новых пользователей.
шоу

1
Это вопрос или перспектива или, может быть, даже мнение, @titoih - это ноль или отсутствие значения, значение, как и любое другое, или это особый случай? «a @ bc» и «a @ bc» - это одно и то же, «ничто» и «ничто» одинаково? С не разреженным индексом ответ - «да» в MongoDB. Другие базы данных (такие как MySQL) сказали бы «нет».
RickN

65

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

Из командной строки

 mongo
use dbName;
db.dropDatabase();
exit

47
Я думаю, что это решение очень агрессивно, я думаю, что этого достаточно, db.collection.dropIndexes()как сказал
cs_stackX

2
@JorgeGarza У меня была такая же проблема. Я только что уронил коллекцию, и после этого все стало работать нормально.
Сандип Субеди

Я случайно инициализировал коллекцию уникальным идентификатором для двух моих полей. Позже, когда я захотел добавить несколько документов с одним и тем же идентификатором, он не позволил бы мне, пока я не удалил коллекцию и не обработал ее повторно.
Меир Снайдер

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

Комментарий @JorgeGarza имеет смысл. Удаленные индексы будут перестроены еще раз файлом схемы при перезапуске сервера. Также это сработало.
retr0

26

Проверьте коллекционные индексы.

У меня была эта проблема из-за устаревших индексов в коллекции для полей, которые должны храниться по другому новому пути.

Mongoose добавляет индекс, когда вы указываете поле как уникальное.


22

В общем, эта ошибка говорит о том, что у вас есть уникальный индекс для определенного поля, например: «email_address», поэтому mongodb ожидает уникальное значение адреса электронной почты для каждого документа в коллекции.

Допустим, ранее в вашей схеме уникальный индекс не был определен, а затем вы зарегистрировали 2 пользователей с одинаковым адресом электронной почты или без адреса электронной почты (нулевое значение).

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

По сути, у вас есть три варианта:

  1. Оставьте коллекцию

    db.users.drop();

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

    db.users.remove({ email_address: null });

  3. Оставьте уникальный индекс:

    db.users.dropIndex(indexName)

Надеюсь, это помогло :)


20

Я хочу объяснить ответ / решение этого, как я объясняю 5-летнему ребенку, чтобы все могли понять.

У меня есть приложение. Я хочу, чтобы люди регистрировались по электронной почте, паролю и номеру телефона. В моей базе данных MongoDB я хочу однозначно идентифицировать людей по их телефонным номерам и электронной почте, так что это означает, что как телефонный номер, так и адрес электронной почты должны быть уникальными для каждого человека.

Однако есть проблема: я понял, что у каждого есть номер телефона, но не у каждого есть адрес электронной почты.

Те, у кого нет адреса электронной почты, пообещали мне, что у них будет адрес электронной почты к следующей неделе. Но я все равно хочу, чтобы они были зарегистрированы - поэтому я говорю им, чтобы они продолжали регистрировать свои номера телефонов, оставляя поле ввода электронной почты пустым.

Они так и делают.

Моя база данных нуждается в уникальном поле адреса электронной почты - но у меня есть много людей с нулевым адресом в качестве адреса электронной почты. Поэтому я перехожу к своему коду и говорю своей схеме базы данных разрешить пустые / пустые поля адресов электронной почты, которые я позже заполню уникальными адресами электронной почты, когда люди, которые пообещали добавить свои электронные письма в свои профили на следующей неделе.

Так что теперь это беспроигрышный вариант для всех (кроме вас; -]): люди регистрируются, я рад получить их данные ... и моя база данных довольна, потому что она хорошо используется ... но как насчет вас? Я еще не дал вам код, который создал схему.

Вот код: ПРИМЕЧАНИЕ. Свойство sparse в электронной почте сообщает моей базе данных о разрешенных пустых значениях, которые впоследствии будут заполнены уникальными значениями.

var userSchema = new mongoose.Schema({
  local: {
    name: { type: String },
    email : { type: String, require: true, index:true, unique:true,sparse:true},
    password: { type: String, require:true },
  },
  facebook: {
    id           : { type: String },
    token        : { type: String },
    email        : { type: String },
    name         : { type: String }
  }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

Надеюсь, я хорошо это объяснил. Счастливого NodeJS кодирования / взлома!


если вам нужен sparseиндекс и uniqueпроверка, а также есть другие поля, которые не требуются, вам нужно использовать эту partialFilterExpressionопцию. Смотрите этот ответ stackoverflow.com/a/34600171/728287
Джанфранко П.


4

В этой ситуации войдите в Mongo и найдите индекс, который вы больше не используете (в случае OP 'email'). Затем выберите Drop Index введите описание изображения здесь


3

Это мой соответствующий опыт:

В схеме «Пользователь» я установил «имя» в качестве уникального ключа, а затем выполнил некоторое выполнение, которое, я думаю, настроило структуру базы данных.

Затем я изменил уникальный ключ как «имя пользователя» и больше не передавал значение «имя» при сохранении данных в базе данных. Таким образом, mongodb может автоматически установить значение 'name' для новой записи как null, что является дубликатом ключа. Я попытался установить ключ 'name' как не уникальный ключ {name: {unique: false, type: String}}в схеме 'User', чтобы переопределить исходную настройку. Однако это не сработало.

Наконец, я сделал свое собственное решение:

Просто установите случайное значение ключа, которое вряд ли будет дублировать ключ «имя» при сохранении записи данных. Просто метод Math '' + Math.random() + Math.random() создает случайную строку.


12
Я не думаю, что это правильное решение, вы просто маскируете проблему.
Рик

Уродливый, но прагматичный
Энтони

3

Я была такая же проблема. Попытки отладки разными способами не могли понять. Я попытался сбросить коллекцию, и после этого она работала нормально. Хотя это не очень хорошее решение, если в вашей коллекции много документов. Но если вы находитесь на ранней стадии разработки, попробуйте сбросить коллекцию.

db.users.drop();

2

Это потому, что уже существует коллекция с таким же именем и конфигурацией. Просто удалите коллекцию из вашего mongodb через оболочку mongo и попробуйте снова.

db.collectionName.remove ()

теперь запустите ваше приложение, оно должно работать


2

У меня была похожая проблема, и я понял, что по умолчанию Mongo поддерживает только одну схему на коллекцию. Либо сохраните новую схему в другой коллекции, либо удалите существующие документы с несовместимой схемой в вашей текущей коллекции. Или найдите способ иметь более одной схемы на коллекцию.


2

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

unique: true

Это может быть возможно, даже если это не сработает. Так что просто нужно удалить коллекцию из MongoDB и перезагрузить сервер.


1

Я получил эту же проблему, когда у меня была следующая конфигурация в моем config / models.js

module.exports.models = {
  connection: 'mongodb',
  migrate: 'alter'
}

Изменение перехода от 'alter' к 'safe' исправило это для меня.

module.exports.models = {
  connection: 'mongodb',
  migrate: 'safe'
}

1

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

примечание: сообщение об ошибке приведет вас в этом случае. у него есть путь, которого больше нет. В моем случае старый путь был ... $ uuid_1 (это индекс!), но новый - .... * priv.uuid_1


1

У меня была та же проблема, когда я пытался изменить схему, определенную с помощью mangoose. Я думаю, что проблема связана с тем, что при создании коллекции был сделан какой-то базовый процесс, такой как описание индексов, которые скрыты от пользователя (по крайней мере, в моем случае). Так что лучшее решение, которое я нашел, это удалить всю коллекцию и начать снова.


0

У меня была такая же проблема. Проблема заключалась в том, что я удалил одно поле из модели. Когда я уронил дБ это исправляет



-3

Измените имя коллекции, если оно уже существует в базе данных, будет отображаться ошибка. И если вы указали какое-либо свойство как уникальное, произойдет та же ошибка.


-4

У меня была та же проблема, которую я решил, удалив uniqueатрибут в свойстве.

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


Вы должны предоставить пример с вашим решением.
Джош Адамс

Сначала очистив коллекцию и / или удалив всю коллекцию из базы данных mongo, это было временное решение. Создание другой записи со схожими значениями, даже если у них были разные идентификаторы, по-прежнему приводило к ошибке дублированного ключа E11000. Я хотел разрешить повторяющиеся значения для этого свойства, поэтому я просто удалил уникальный атрибут.
davyCode

-7

Очистите коллекцию или удалите всю коллекцию из базы данных MongoDB и повторите попытку позже.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.