E11000 mongodbマングースの重複キーエラーインデックス


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 }"} 

私はdbコレクションをチェックしましたが、そのような重複するエントリは存在しません。何が間違っているのか教えてください。

FYI- req.body.emailreq.body.password値をフェッチしています。

私もこの投稿をチェックしましたが、助けはありませんSTACK LINK

完全に削除した場合、ドキュメントが挿入されます。それ以外の場合は、local.emailにエントリがあっても、エラー「重複」エラーがスローされます。


1
同じエラーが発生しました!開発中、自動インデックス作成を無効にし、小文字のスキーマ名/キーを使用していました。その後、代わりにTitleCaseを使用することを決定しましたが、インデックス名を更新できませんでした(つまり、TitleCaseではなくtitleCase)。したがって、インデックス作成を有効にすると、このエラーが発生しました。それを理解するのに少し時間がかかりました。すべての名前/キーがどこでも正確に命名されていることを確認する必要があります。
Jeach

6
同じエラーが発生し、マングースモデルをunique: falseに設定しても影響はありませんでした。最初にテーブルを削除する必要があり、それが機能することに気づきました。あなたはのような何かをすることができますdb.whateverthecollection.drop({})。注意してください、それはコレクションを削除します。
ペレ

回答:


241

エラーメッセージはnull、メールとしてのレコードがすでにあることを示しています。つまり、メールアドレスのないユーザーがすでに存在しています。

これに関連するドキュメント:

ドキュメントに一意のインデックスのインデックス付きフィールドの値がない場合、インデックスはこのドキュメントのnull値を格納します。一意の制約があるため、MongoDBは、インデックス付きフィールドがない1つのドキュメントのみを許可します。インデックス付きフィールドの値のないドキュメントが複数ある場合、またはインデックス付きフィールドがない場合、重複キーエラーでインデックスの作成が失敗します。

一意性制約をスパースインデックスと組み合わせて、一意性インデックスからこれらのnull値をフィルタリングし、エラーを回避できます。

一意のインデックス

スパースインデックスには、インデックスフィールドにnull値が含まれている場合でも、インデックスフィールドを持つドキュメントのエントリのみが含まれます。

言い換えると、スパースインデックスは、すべてnull値を持つ複数のドキュメントで問題ありません。

スパースインデックス


コメントから:

あなたのエラーは、キーの名前であることを述べているmydb.users.$email_1私はあなたが両方のインデックスがあることを疑うになりたusers.emailusers.local.email(現時点では、古い、未使用であること前者)。Mongooseモデルからフィールドを削除しても、データベースには影響しません。mydb.users.getIndexes()これに該当するかどうかを確認し、不要なインデックスをで手動で削除してくださいmydb.users.dropIndex(<name>)


1
私はそのnullドキュメントを削除し、それは機能しました:) +1 ..thx for help
Trialcoder

70
あなたのエラーは、キーの名前であることを述べているmydb.users.$email_1私はあなたが両方のインデックスがあることを疑うになりたusers.emailusers.local.email(現時点では、古い、未使用であること前者)。Mongooseモデルからフィールドを削除しても、データベースには影響しません。mydb.users.getIndexes()これに該当するかどうかを確認し、不要なインデックスをで手動で削除してくださいmydb.users.dropIndex(<name>)
RickN 2014年

17
またはdb.users.dropIndexes()、複数のインデックスを変更する場合に使用します
cs_stackX '31

1
新しいユーザーのユーザー名を設定せずにmongooseプラグインpassport-local-mongooseを使用していたとき、これは私にとって問題でした。
sshow

1
それは問題であるか、見方であるか、意見かもしれません。@ titoih-nullであるか、値がないことは他の場合と同じように値ですか、それとも特殊なケースですか?「a @ bc」と「a @ bc」は同じですが、「nothing」と「nothing」も同じですか?非スパースインデックスの場合、MongoDBでは答えは「はい」です。他のデータベース(MySQLなど)は「いいえ」と表示します。
RickN

65

まだ開発環境にいる場合は、db全体を削除して、新しいスキーマからやり直します。

コマンドラインから

 mongo
use dbName;
db.dropDatabase();
exit

47
このソリューションは非常に積極的だと思いますdb.collection.dropIndexes()。cs_stackXが言ったように、これで十分だと思います
JorgeGarza

2
@JorgeGarza同じ問題が発生しました。コレクションを削除したところ、その後はすべて正常に動作し始めました。
Sandip Subedi

2つのフィールドの一意のIDでコレクションを誤って初期化しました。後で同じIdで複数のドキュメントを追加したいときは、コレクションを削除して再度アクセスするまで、許可されませんでした。
Meir Snyder、

1
開発が初めての場合、これは、ギガバイトのユーザーデータが既に格納されているときにこの問題に
遭遇

@JorgeGarzaのコメントには意味があります。削除されたインデックスは、サーバーの再起動時にスキーマファイルによって再構築されます。また、うまくいきました。
retr0

26

コレクションインデックスを確認します。

別の新しいパスで保存する必要があるフィールドのコレクションの古いインデックスが原因で、この問題が発生しました。

フィールドを一意として指定すると、Mongooseはインデックスを追加します。


22

まあ基本的にこのエラーは、たとえば「email_address」などの特定のフィールドに一意のインデックスがあることを示しているため、mongodbはコレクション内の各ドキュメントに一意の電子メールアドレス値を期待しています。

たとえば、スキーマの前半で一意のインデックスが定義されておらず、同じメールアドレスまたはメールアドレスなし(null値)で2人のユーザーを登録したとします。

後で、あなたは間違いがあったのを見ました。そのため、スキーマに一意のインデックスを追加して修正しようとします。ただし、コレクションには既に重複があるため、エラーメッセージは重複した値を再度挿入できないことを示しています。

基本的に3つのオプションがあります。

  1. コレクションをドロップ

    db.users.drop();

  2. その値を持つドキュメントを見つけて削除します。値がnullだったとしましょう。次のようにして削除できます。

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

  3. 一意のインデックスを削除します。

    db.users.dropIndex(indexName)

これがお役に立てば幸いです:)


20

私は5歳の子供に説明しているように、これに対する答え/解決策を説明して、誰もが理解できるようにします。

私はアプリを持っています。メール、パスワード、電話番号を使って登録してもらいたいです。私のMongoDBデータベースでは、電話番号とメールの両方に基づいて人を一意に識別したいので、電話番号とメールの両方がすべての人に対して一意である必要があります。

しかし、問題があります。誰もが電話番号を持っているが、誰もがメールアドレスを持っているわけではないことに気付きました。

メールアドレスをお持ちでない方は、来週までにメールアドレスを取得すると約束してくれました。しかし、とにかく登録してもらいたいので、email-input-fieldを空のままにして、電話番号の登録を続行するように伝えます。

彼らはそうします。

私のデータベースには一意のメールアドレスフィールドが必要ですが、メールアドレスが「null」の人がたくさんいます。そこで、コードにアクセスして、データベーススキーマに空/ nullのメールアドレスフィールドを許可するように指示します。このフィールドには、来週プロファイルにメールを追加すると約束した人がいるときに、メールの一意のアドレスを入力します。

だから、今は誰にとっても有利なものです(あなただけですが;-]):人々は登録し、私は彼らのデータを手に入れました...そして私のデータベースはそれがうまく使用されているので幸せです...しかしあなたはどうですか?スキーマを作成するコードはまだ提供していません。

次にコードを示します。 注:電子メールのスパースプロパティは、データベースにnull値を許可するように指示するものです。

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
Gianfranco P.


4

この状況では、Mongoにログインして、もう使用していないインデックスを検索します(OPの場合は「電子メール」)。次に、インデックスの削除を選択します ここに画像の説明を入力してください


3

これは私の関連する経験です:

「ユーザー」スキーマで、「名前」を一意のキーとして設定してから、データベース構造を設定したと思われる実行を実行しました。

次に、一意のキーを「username」に変更し、データベースにデータを保存するときに「name」の値を渡さなくなりました。そのため、mongodbは新しいレコードの 'name'値を重複キーであるnullとして自動的に設定する場合があります。一意ではないキーとして「名前」キーを設定しようとしました {name: {unique: false, type: String}}元の設定を上書きするために、「ユーザー」スキーマで。ただし、機能しませんでした。

ついに、私は自分の解決策を作りました:

データレコードを保存するときに、重複しない可能性のあるランダムなキー値を 'name'キーに設定するだけです。単にMathメソッド'' + Math.random() + Math.random() はランダムな文字列を作成します。


12
これは有効な解決策ではないと思います。問題を隠蔽するだけです。
Rick

醜いが実用的
アンソニー

3

同じ問題がありました。さまざまな方法でデバッグを試みたが理解できなかった。コレクションをドロップしてみましたが、その後は問題なく動作しました。コレクションに多数のドキュメントがある場合、これは適切なソリューションではありません。ただし、開発の初期段階にある場合は、コレクションを削除してみてください。

db.users.drop();

2

これは、構成と同じ名前のコレクションが既に存在するためです。mongoシェルを使用してmongodbからコレクションを削除し、再試行してください。

db.collectionName.remove()

動作するはずのアプリケーションを実行します


2

同様の問題があり、mongoはデフォルトでコレクションごとに1つのスキーマしかサポートしないことに気付きました。新しいスキーマを別のコレクションに保存するか、現在のコレクション内の互換性のないスキーマを持つ既存のドキュメントを削除してください。または、コレクションごとに複数のスキーマを持つ方法を見つけます。


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

スキーマからプロパティを除去した後、同じ問題の後保存時にいくつかのインデックスを最初に作成した。スキーマからプロパティを削除すると、インデックスがまだ存在する、存在しないプロパティがnull値になります。インデックスを削除したり、ゼロから新しいコレクションを開始したりすると、ここで役立ちます。

注:この場合、エラーメッセージが表示されます。それはもう存在しないパスを持っています。私の場合、古いパスは... $ uuid_1(これはインデックスです!)でしたが、新しいパスは.... * priv.uuid_1です。


1

mangooseを使用して定義されたスキーマを変更しようとしたときにも、同じ問題が発生しました。問題は、ユーザーから隠されたインデックスを記述するようなコレクションを作成するときに行われるいくつかの基本的なプロセスがあるためだと思います(少なくとも私の場合)。もう一度始めます。


0

同じ問題がありました。問題は、モデルから1つのフィールドを削除したことです。私はそれを修正しました



-3

コレクション名がデータベースにすでに存在する場合は変更してください。エラーが表示されます。また、一意のプロパティを指定すると、同じエラーが発生します。


-4

同じ問題があったのでunique、プロパティの属性を削除して解決しました。

スキーマの一意のプロパティ値を検証またはチェックする別の方法を見つけてください。


ソリューションの例を提供する必要があります。
ジョシュアダムス

最初にコレクションをクリアしたり、mongoデータベースからコレクション全体を削除したりすることは機能しましたが、一時的な解決策でした。IDが異なっていても値が類似している別のレコードを作成すると、E11000重複キーエラーが発生しました。そのプロパティの重複値を許可したかったので、一意の属性を削除しました。
davyCode 2018

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.