web-dev-qa-db-ja.com

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

以下はuser.jsモデルの私のuserスキーマです -

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は値をフェッチしています。

私もこの記事をチェックしたが助けがない スタックリンク

完全に削除した場合はドキュメントが挿入されます。それ以外の場合はlocal.emailにエントリがあってもエラー "Duplicate"が発生します

176
Trialcoder

エラーメッセージは、電子メールとしてnullを含むレコードがすでにあることを示しています。言い換えれば、あなたはすでにEメールアドレスのないユーザーを持っています。

これに関連する文書:

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

ユニーク制約と疎索引を組み合わせて、ユニーク索引からこれらのNULL値をフィルターに掛け、エラーを回避することができます。

ユニークインデックス

疎索引には、索引フィールドにNULL値が含まれていても、索引フィールドを持つ文書の項目のみが含まれます。

言い換えれば、疎索引は、すべてnull値を持つ複数の文書で問題ありません。

疎索引


コメントから:

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

181
RikkusRukkus

それでも開発環境にいるのであれば、データベース全体を削除して、新しいスキーマからやり直すことにします。

コマンドラインから

➜ mongo
use dbName;
db.dropDatabase();
exit
50
Rick

コレクションインデックスを確認してください。

私はその問題を持っていました、フィールドのためのコレクションの古いインデックスは別の新しいパスによって保存されるべきです。

Mongooseはfieldをuniqueに指定するとインデックスを追加します。

15
Yegor

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

そのため、スキーマの前半で一意のインデックスが定義されていないとします。次に、同じ電子メールアドレスまたは電子メールアドレスなし(null値)で2人のユーザーをサインアップしました。

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

基本的に3つの選択肢があります。

  1. コレクションを削除する

    db.users.drop();

  2. その値を持つ文書を見つけて削除します。値がnullだったとしましょう、あなたはそれを使ってそれを削除することができます:

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

  3. Uniqueインデックスを削除します。

    db.users.dropIndex(indexName)

これが助けになれば幸いです:)

14
Daksh Miglani

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

私はapp.Iを持っています私は人々に彼らのEメール、パスワードと電話番号で登録して欲しいです。私のMongoDBデータベースでは、自分の電話番号とEメールの両方に基づいて個人を一意に識別したいのです。つまり、電話番号とEメールの両方がすべての個人に対して一意である必要があります。

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

Eメールアドレスを持っていない人は、来週までにEメールアドレスを持つことを私に約束しました。しかし、私は彼らがとにかく登録されることを望みます - それで私は彼らがemail-input-fieldを空のままにするので彼らの電話番号を登録し続けるように彼らに言います。

彼らはそうします。

私のデータベースはユニークなEメールアドレスフィールドを必要とします - しかし私は彼らのEメールアドレスとして 'null'を持つ人々をたくさん持っています。そこで私は自分のコードに行き、空の/ nullのEメールアドレスフィールドを許可するようにデータベーススキーマに指示します。これは、来週自分のプロファイルにEメールを追加することを約束した人が後で入力します。

だから、今ではみんなにとってメリットがあります(しかしあなたは - ]):人々が登録し、私は彼らのデータを持っていてうれしいです...そして私のデータベースはうまく使われているのでうれしいです...しかしあなたはどうですか?スキーマを作成したコードはまだ提供していません。

コードは次のとおりです。注:emailのsparseプロパティは、後で一意の値で埋められる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コーディング/ハッキング!

8
Daggie Blanqx

私は同じような問題に直面しました、私はただ特定の分野のインデックスをクリアして、それから私のために働きます。 https://docs.mongodb.com/v3.2/reference/method/db.collection.dropIndexes/

7
mad Man

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

'User'スキーマでは、 'name'を一意のキーとして設定してから実行したところ、データベース構造が設定されたと思います。

それから私は 'username'としてユニークなキーを変更しました、そして私がデータベースにデータを保存したときもはや 'name'値を渡しませんでした。そのため、mongodbは自動的に新しいレコードの 'name'値を重複キーであるnullに設定することがあります。元の設定を上書きするために、 'User'スキーマ内の固有のキー{name: {unique: false, type: String}}ではないセット 'name'キーを試しました。しかし、うまくいきませんでした。

最後に、私は私自身の解決策を作りました:

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

4
Kobe Luo

私は同じ問題を抱えていました。さまざまな方法でデバッグしようとしたが理解できませんでした。コレクションを削除しようとしましたが、その後はうまくいきました。コレクションに多数のドキュメントがある場合、これは良い解決策ではありませんが。しかし、あなたが開発の初期段階にいるのなら、コレクションを削除してみてください。

db.users.drop();
3
Sandip Subedi

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

2
Embedded_Mugs

これは、configurationと同じ名前のコレクションがすでに存在するためです。ただ、mongo Shellを介してmongodbからコレクションを削除して、もう一度やり直してください。

db.collectionName.remove()

これでうまくいくはずです。

2
Ignatius Andrew

私はマンゴースを使用して定義されたスキーマを変更しようとしたときに私は同じ問題を抱えていた。私は問題がユーザーから隠されているインデックスを記述するようなコレクションを作成するときに行われるいくつかの根本的なプロセスがあるという理由によると思います。そしてまた始めなさい。

1
Rahul P

私のconfig/models.jsに以下の設定があった時にも同じ問題がありました

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

変更を 'alter'から 'safe'に変更することで修正されました。

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

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

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

1
chhtm

私は同じ問題を抱えていました。問題は、モデルから1つのフィールドを削除したことです。私はdbを落としたときそれは修正する

1
user86168

私もこの問題に直面しており、それを解決しました。このエラーは、Eメールが既にここに存在していることを示しています。だからあなたはちょうどあなたのModel for email属性からこの行を削除する必要があります。

unique: true

これが機能しない場合でも可能性があります。 MongoDBからコレクションを削除してサーバーを再起動するだけです。

1
Inamur Rahman