1. ホーム
  2. node.js

[解決済み】E11000重複キーエラー mongodb mongooseのインデックス

2022-01-25 13:51:26

質問

以下は、私の 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');

このようにして、DBに保存しています。

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コレクションをチェックし、そのような重複したエントリが存在しない。

参考までに-。 req.body.emailreq.body.password は値を取得しています。

この記事もチェックしましたが、役に立ちませんでした。 スタックリンク

完全に削除すると挿入されますが、そうでなければ、local.emailにエントリがあっても、エラー"Duplicate"をスローします。

解決するには?

を持つレコードがすでに存在するというエラーメッセージが表示されます。 null を電子メールとして使用します。つまり、Eメールアドレスのないユーザがすでに存在することになります。

そのための関連ドキュメントです。

もしドキュメントがユニークインデックスでインデックスされたフィールドの値を持っていない場合、インデックスはこのドキュメントのヌル値を格納します。一意制約があるので、MongoDB はインデックス付きフィールドを欠いたドキュメントをひとつだけ許可します。インデックス対象フィールドの値がない、あるいはインデックス対象フィールドがないドキュメントが複数ある場合は、重複キーエラーでインデックスの構築に失敗します。

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

ユニークインデックス

スパースインデックスは、インデックスフィールドがNULL値を含んでいても、インデックスされたフィールドを持つドキュメントのエントリのみを含む。

言い換えれば、スパースインデックスは、複数の文書がすべて null の値を指定します。

スパースインデックス


コメントより

あなたのエラーは、キーの名前が mydb.users.$email_1 の両方にインデックスがあるのでは? users.emailusers.local.email (前者は古くて今は使われていない)。Mongoose モデルからフィールドを削除しても、データベースには影響しません。でチェックします。 mydb.users.getIndexes() で不要なインデックスを手動で削除してください。 mydb.users.dropIndex(<name>) .