[node.js] mongodb 몽구스의 E11000 중복 키 오류 색인

다음은 모델의 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값을 가져 오는 있습니다.

나는 또한이 게시물하지만 도움이 확인 STACK LINK를

완전히 제거하면 문서가 삽입됩니다. 그렇지 않으면 local.email에 항목이 있어도 “중복”오류가 발생합니다.



답변

오류 메시지는 이미 null이메일로 기록이 있음 을 나타냅니다. 즉, 이메일 주소가없는 사용자가 이미 있습니다.

이에 대한 관련 문서 :

문서에 고유 색인의 색인화 된 필드 값이없는 경우 색인은이 문서의 널값을 저장합니다. 고유 제한 조건으로 인해 MongoDB는 색인 필드가없는 하나의 문서 만 허용합니다. 인덱싱 된 필드에 대한 값이없는 문서가 두 개 이상이거나 인덱싱 된 필드가 없으면 중복 키 오류와 함께 인덱스 빌드가 실패합니다.

고유 제한 조건을 희소 색인과 결합하여 고유 색인에서 이러한 널값을 필터링하고 오류를 피할 수 있습니다.

고유 인덱스

희소 색인은 색인 필드에 널값이 포함되어 있어도 색인 필드가있는 문서의 항목 만 포함합니다.

다시 말해, 여러 문서에 모두 null값 이있는 희소 색인은 정상입니다 .

희소 색인


의견에서 :

귀하의 오류에 따르면 키 이름이 지정 mydb.users.$email_1되어 users.email있으며 users.local.email(이전은 오래되었고 사용되지 않은) 둘 다에 대한 색인이 있다고 의심합니다 . 몽구스 모델에서 필드를 제거해도 데이터베이스에는 영향을 미치지 않습니다. 이 mydb.users.getIndexes()경우에 체크하고를 사용하여 원하지 않는 인덱스를 수동으로 제거하십시오 mydb.users.dropIndex(<name>).


답변

여전히 개발 환경에 있다면 전체 db를 삭제하고 새 스키마로 다시 시작합니다.

명령 행에서

 mongo
use dbName;
db.dropDatabase();
exit


답변

컬렉션 인덱스를 확인하십시오.

필드에 대한 컬렉션의 오래된 인덱스로 인해 다른 문제가 발생했습니다. 다른 경로로 저장해야합니다.

몽구스는 필드를 고유 한 것으로 지정할 때 색인을 추가합니다.


답변

기본적으로이 오류는 “email_address”와 같은 특정 필드에 고유 색인이 있으므로 mongodb는 콜렉션의 각 문서에 대해 고유 한 이메일 주소 값을 예상합니다.

예를 들어 스키마 초기에 고유 인덱스가 정의되지 않은 경우 동일한 전자 메일 주소를 사용하거나 전자 메일 주소가없는 (널 값) 2 명의 사용자를 등록했습니다.

나중에 실수가 있음을 알았습니다. 스키마에 고유 색인을 추가하여 정정하려고합니다. 그러나 컬렉션에 이미 중복 항목이 있으므로 중복 값을 다시 삽입 할 수 없다는 오류 메시지가 나타납니다.

본질적으로 세 가지 옵션이 있습니다.

  1. 컬렉션 삭제

    db.users.drop();

  2. 해당 값을 가진 문서를 찾아 삭제하십시오. 값이 null이라고 가정하면 다음을 사용하여 삭제할 수 있습니다.

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

  3. 고유 색인을 삭제하십시오.

    db.users.dropIndex(indexName)

나는 이것이 도움이되기를 바랍니다 🙂


답변

나는 5 살짜리 아이에게 설명하는 것처럼 이것에 대한 답 / 해결책을 설명하고 싶다. 그래서 모든 사람들이 이해할 수있다.

앱이 있는데 사람들이 이메일, 비밀번호 및 전화 번호로 등록하기를 원합니다. 내 MongoDB 데이터베이스에서 전화 번호와 이메일을 기반으로 사람들을 고유하게 식별하고 싶습니다. 이는 전화 번호와 이메일이 모든 사람에게 고유해야 함을 의미합니다.

그러나 문제가 있습니다. 모든 사람이 전화 번호를 가지고 있지만 모든 사람이 전자 메일 주소를 가지고 있지 않다는 것을 깨달았습니다.

이메일 주소가없는 사람들은 다음 주까지 이메일 주소를 가지겠다고 약속했습니다. 그러나 나는 그들이 어쨌든 등록되기를 원한다. 그래서 나는 그들이 이메일 입력 필드를 비워 둘 때 전화 번호 등록을 계속하라고 말한다.

그들은 그렇게합니다.

내 데이터베이스에는 고유 한 전자 메일 주소 필드가 필요하지만 전자 메일 주소로 ‘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 코딩 / 해킹!


답변

나는 비슷한 문제에 직면했다. 나는 단지 특정 필드의 인덱스를 지우고 나에게 효과적이다.
https://docs.mongodb.com/v3.2/reference/method/db.collection.dropIndexes/


답변

이 경우 Mongo에 로그인하여 더 이상 사용하지 않는 색인을 찾으십시오 (OP의 경우 ‘이메일’). 그런 다음 인덱스 삭제를 선택하십시오.
여기에 이미지 설명을 입력하십시오