mongodb 몽구스의 E11000 중복 키 오류 색인


228

다음은 모델의 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에 항목이 있어도 "중복"오류가 발생합니다.


1
같은 오류가 있었다! 개발 과정에서 자동 인덱싱을 비활성화하고 소문자 스키마 이름 / 키를 사용했습니다. 나중에 TitleCase를 대신 사용하기로 결정했지만 색인 이름을 업데이트하지 못했습니다 (예 : TitleCase 대신 titleCase). 따라서 인덱싱을 활성화했을 때이 오류가 발생했습니다. 알아내는 데 시간이 조금 걸렸습니다. 모든 이름 / 키의 이름이 어디에서나 정확하게 지정되도록해야합니다.
Jeach

6
나는 같은 오류가 있었고 몽구스 모델을 설정해 unique: false도 아무런 영향을 미치지 않았습니다. 나는 먼저 테이블을 떨어 뜨려야한다는 것을 깨달았습니다. 당신은 같은 것을 할 수 있습니다 db.whateverthecollection.drop({}). 컬렉션을 삭제합니다.
Pere

1
_id : mongoose.Types.ObjectId 고유 ID가 필요하기 때문에 추가
Mayank Pandav

답변:


239

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

이에 대한 관련 문서 :

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

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

고유 인덱스

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

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

희소 색인


의견에서 :

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


1
난 그냥 그 null 문서를 제거하고 그것은 작동 :) 도움을 위해 +1 ..thx
Trialcoder

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

17
또는 사용 db.users.dropIndexes() 여러 인덱스를 변경 경우
cs_stackX

1
이것은 새로운 사용자의 사용자 이름을 설정하지 않고 mongoose plugin passport-local-mongoose를 사용할 때 문제였습니다.
sshow

1
@titoih-그것은 문제 또는 관점이거나 어쩌면 의견 일 수도 있습니다. null이거나 다른 값처럼 값이 없으면 특별한 경우입니까? "a @ bc"와 "a @ bc"는 동일합니다. "아무것"과 "아무것도"같은가요? 희소 색인이없는 경우 MongoDB에서 답은 "예"입니다. 다른 데이터베이스 (예 : MySQL)는 "아니요"라고 말합니다.
RickN

64

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

명령 행에서

 mongo
use dbName;
db.dropDatabase();
exit

46
나는이 솔루션이 매우 공격적이라고 생각 db.collection.dropIndexes()한다. cs_stackX가 말한 것처럼 충분하다고 생각한다
JorgeGarza

2
@JorgeGarza 나는 같은 문제가있었습니다. 방금 컬렉션을 삭제하고 그 후에 모든 것이 잘 작동하기 시작했습니다.
Sandip Subedi

실수로 두 필드에 대한 고유 ID로 컬렉션을 초기화했습니다. 나중에 동일한 ID로 여러 문서를 추가하고 싶을 때 컬렉션을 삭제하고 다시 액세스 할 때까지는 허용되지 않습니다.
Meir Snyder

1
당신이 당신의 개발에 새로운 경우 사용자 기가 바이트의 데이터가 이미 저장 한 후,이이 문제에이 ...보다는 실행을 해결하는 방법을 좋은 실험 기회와 그림은
Janac 미나

@JorgeGarza의 의견은 의미가 있습니다. 삭제 된 인덱스는 서버가 다시 시작될 때 스키마 파일에 의해 다시 한 번 다시 작성됩니다. 또한 효과가있었습니다.
retr0

26

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

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

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


21

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

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

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

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

  1. 컬렉션 삭제

    db.users.drop();

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

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

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

    db.users.dropIndex(indexName)

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


18

나는 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 코딩 / 해킹!


sparse색인 및 unique유효성 검사 를 원하고 필요 하지 않은 다른 필드가 있는 경우이 partialFilterExpression옵션 을 사용해야합니다 . 이 답변보기 stackoverflow.com/a/34600171/728287
Gianfranco P.


4

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


3

이것은 내 관련 경험입니다.

'User'스키마에서 'name'을 고유 키로 설정 한 다음 데이터베이스 구조를 설정했다고 생각하는 실행을 실행했습니다.

그런 다음 고유 키를 'username'으로 변경하고 데이터베이스에 데이터를 저장할 때 더 이상 'name'값을 전달하지 않았습니다. 따라서 mongodb는 새 레코드의 'name'값을 중복 키인 null로 자동 설정할 수 있습니다. 'name'키를 고유 키가 아닌 것으로 시도했습니다. {name: {unique: false, type: String}}원래 설정을 재정의하기 위해 'User'스키마에서 가 . 그러나 작동하지 않았습니다.

마침내 나는 내 자신의 해결책을 만들었다.

데이터 레코드를 저장할 때 'name'키와 중복되지 않는 임의의 키 값만 설정하십시오. 간단히 Math 메소드 '' + Math.random() + Math.random() 는 임의의 문자열을 만듭니다.


12
나는 이것이 유효한 해결책이라고 생각하지 않으며, 단지 당신의 문제를 숨기고 있습니다.
Rick

미운하지만 실용적인
안토니

3

나는 같은 문제가 있었다. 다른 방법으로 디버깅을 시도했지만 알아낼 수 없었습니다. 컬렉션을 삭제하려고 시도한 후 정상적으로 작동했습니다. 컬렉션에 많은 문서가있는 경우이 방법은 좋지 않습니다. 그러나 개발 초기 단계에 있다면 컬렉션을 삭제하십시오.

db.users.drop();

2

구성과 이름이 같은 컬렉션이 이미 있기 때문입니다. mongob에서 mongoshell을 통해 컬렉션을 제거하고 다시 시도하십시오.

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

나는 같은 문제가 있었다. 문제는 모델에서 하나의 필드를 제거했다는 것입니다. DB를 삭제하면 수정됩니다.


0

미래의 개발자를 위해 나침반을 사용하여 INDEX TAB에서 색인을 삭제하는 것이 좋습니다 ... 이것은 컬렉션의 모든 문서를 삭제하지 않습니다 색인 관리


-3

컬렉션 이름이 이미 데이터베이스에 존재하면 변경하면 오류가 표시됩니다. 그리고 고유 한 속성을 지정하면 동일한 오류가 발생합니다.


-4

동일한 문제가 있었지만 unique 속성 속성을 .

스키마의 고유 속성 값을 확인하거나 확인하는 다른 방법을 찾으십시오.


솔루션과 함께 예제를 제공해야합니다.
Josh Adams

먼저 컬렉션을 지우거나 mongo 데이터베이스에서 전체 컬렉션을 삭제하면 일시적인 해결책이었습니다. ID가 다른 경우에도 비슷한 값으로 다른 레코드를 작성하면 E11000 중복 키 오류가 발생합니다. 해당 속성에 중복 값을 허용하고 싶기 때문에 고유 속성을 간단히 제거했습니다.
davyCode

-7

콜렉션을 지우거나 MongoDB 데이터베이스에서 전체 콜렉션을 삭제 한 후 나중에 다시 시도하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.