몽구스 고유 색인이 작동하지 않습니다!


96

MongoDB가 인덱스를 기반으로 중복 값을 감지하도록하려고합니다. MongoDB에서 이것이 가능하다고 생각하지만 Mongoose 래퍼를 통해 모든 것이 깨진 것처럼 보입니다. 그래서 다음과 같이 :

User = new Schema ({
  email: {type: String, index: {unique: true, dropDups: true}}
})

동일한 이메일로 2 명의 사용자를 저장할 수 있습니다. 꿰매다.

https://github.com/LearnBoost/mongoose/issues/56 에서 동일한 문제가 표현 되었지만 해당 스레드는 오래되어 아무데도 없습니다.

지금은 사용자를 찾기 위해 수동으로 db를 호출하고 있습니다. 이 호출은 "이메일"이 인덱싱되므로 비용이 많이 들지 않습니다. 그러나 기본적으로 처리되도록하는 것이 여전히 좋습니다.

누구든지 이것에 대한 해결책이 있습니까?


1
나쁜 소식은 여전히 ​​문제입니다. mongod v2.4.3, mongoose v3.6.20
damphat

Unique는 내 호스트 중 하나에서 작동하는 것 같지만 다른 호스트에서 정확히 동일한 노드 / 몽구스 코드를 사용하여 고유를 적용하지 못합니다. 제대로 작동하는 호스트는 단일 mongod 3.4.10을 실행하고, 그렇지 않은 호스트는 mongod 3.2.17로 복제 세트를 실행합니다. 두 호스트 모두 처음부터 컬렉션을 생성하므로 기존 dups는 문제가되지 않습니다. 이 페이지에서 대부분의 솔루션을 시도해 보았고 작동했던 것은 @Isaac Pak의 mongoose-unique-validator였습니다.
Maksym

답변:


94

이런! mongo를 다시 시작하면됩니다.


4
동일한 문제가 발생하지만 OSX에서 mongo를 다시 시작하는 방법을 찾을 수 없습니다. 프로세스를 종료하면 자동으로 다시 생성되고 고유 인덱스가 여전히 작동하지 않습니다. 아이디어가 있습니까?
ragulka

7
"죄송합니다. mongo를 다시 시작해야합니다"란 무슨 뜻입니까?! 데이터베이스를 다운시키지 않고 인덱스를 추가하는 것이 불가능하다는 말입니까?
andrewrk

7
이것은 사실이 아닙니다. 색인을 추가하기 위해 mongo를 다시 시작할 필요가 없습니다.
JohnnyHK

1
독특한 것을 위해 .. 나는 mongo를 다시 시작해야했다 .. 그리고 그것은 작동했다 .. 감사합니다!
Muhammad Ahsan Ayaz

2
다시 시작해 보았습니다. 또한 재 인덱싱. 이 문제를 해결하려면 데이터베이스를 삭제해야했습니다. 문제는 인덱스를 추가하기 전에 이미 중복이 존재했기 때문에 프로덕션 DB에서 중복을 제거한 다음 다시 시작해야한다는 것입니다.
isimmons

40

이런! mongo를 다시 시작하면됩니다.

또한 다음을 사용하여 다시 색인화합니다.

mongo <db-name>
> db.<collection-name>.reIndex()

테스트에서 중요한 데이터가 없기 때문에 다음을 수행 할 수도 있습니다.

mongo <db-name>
> db.dropDatabase()

16
db.dropDatabase ()는 데이터베이스를 지 웁니다!
Isaac Pak

28

같은 문제에 부딪 혔습니다. 이미 db에 사용자를 추가 한 후 email필드에 대한 고유 한 제약 조건을 추가했으며 UserSchema여전히 중복 이메일로 사용자를 저장할 수있었습니다. 다음을 수행하여이 문제를 해결했습니다.

1) 사용자 컬렉션에서 모든 문서를 제거합니다.

2) mongo 셸에서 다음 명령을 실행합니다. db.users.createIndex({email: 1}, {unique: true})

1 단계와 관련하여 Mongo의 문서에서 다음 사항에 유의하십시오.

MongoDB는 컬렉션에 인덱스에 대한 고유 제약 조건을 위반하는 데이터가 이미 포함되어있는 경우 지정된 인덱스 필드에 고유 인덱스를 만들 수 없습니다.

https://docs.mongodb.com/manual/core/index-unique/


11

이 동작은 Mongo에 일부 중복 항목을 남긴 경우에도 발생합니다. Mongoose는 애플리케이션이 시작될 때 Mongo에서 생성을 시도합니다.

이를 방지하려면 다음과 같이이 오류를 처리 할 수 ​​있습니다.

yourModel.on('index', function(err) {
  if (err?) {
    console.error err
  }
);

10

좋아, 필드에 인덱스를 추가하고 고유 속성을 설정하여 mongoshell에서이 문제를 해결할 수있었습니다.

db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});

Shell은 다음과 같이 응답해야합니다.

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

이제 mongoshell에서 빠르게 테스트합니다.

var doc = {fieldName: 'abc'};
db.<collectionName>.insert(doc)

제공해야합니다 : WriteResult ({ "nInserted": 1})

그러나 다시 반복 할 때 :

db.<collectionName>.insert(doc)

줄게:

WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1  dup key: { : \"martyna@martycud.com\" }"
    }
})

10

다음과 같이했습니다.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const FooSchema = new Schema({
   name: { type: String, required: true, index: true, unique: true }
});

const Foo = mongoose.model('Foo', FooSchema);

Foo.createIndexes();

module.exports = Foo

Foo.createIndexes()코드가 실행될 때 다음과 같은 사용 중단 경고가 표시되는 bc 줄을 추가 했습니다.

(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

Foo.createIndexes()비동기 인지 확실하지 않지만 AFAIK가 제대로 작동하는 것 같습니다.


문제를 해결하는 질문에 대한 유일한 답은 문제를 중심으로 진행됩니다.
Saksham Gupta

이 답변이 도움이되었습니다. 내가 놓친 것은 index: true내 고유 색인이 생성되는 것뿐이었습니다.
elcid


6

Mongoose는 응용 프로그램 수준에서 고유 한 인덱스를 적용 할 때 약간 느슨합니다. 따라서 mongo cli를 사용하여 데이터베이스 자체에서 고유 한 인덱스를 적용하거나 uniqueUserSchema 바로 뒤에 다음 코드 줄을 작성하여 mongoose에게 인덱스에 대해 진지하다고 명시 적으로 알리는 것이 좋습니다.

UserSchema.index({ username: 1, email: 1 }, { unique: true});

이렇게하면 UserSchema의 usernameemail필드 모두에 고유 인덱스가 적용됩니다 . 건배.


6
파티에 조금 늦었지만 "고유 인덱스를 적용 할 때 약간 느슨한"ORM이 좋은 점은 무엇입니까?
Imre_G

어떤 식 으로든 도움이되지 않는 비판적인 댓글이 얼마나 좋은지. 이 솔루션은 견고하고 생산 준비가되어 있습니다.
Isaac Pak

4

Mongoose는 다음 중 하나에 해당하는 경우 자동으로 고유 인덱스를 추가하지 못합니다.

  1. 컬렉션에 이미 같은 이름의 색인이 있습니다.
  2. 컬렉션에 이미 인덱싱 된 필드와 중복 된 문서가 포함되어 있습니다.

첫 번째 경우에는로 인덱스를 나열 db.collection.getIndexes()하고로 이전 인덱스를 삭제합니다 db.collection.dropIndex("index_name"). Mongoose 애플리케이션을 다시 시작하면 새 색인이 올바르게 추가되어야합니다.

두 번째 경우에는 Mongoose 애플리케이션을 다시 시작하기 전에 중복 항목을 제거해야합니다.


3

몽구스 고유 유효성 검사기

이 플러그인을 사용하는 방법 :

1) npm install --save mongoose-unique-validator

2) 스키마에서 다음 가이드를 따르십시오.

// declare this at the top
var mongoose = require('mongoose');
var uniqueValidator = require('mongoose-unique-validator');

// exampleSchema = mongoose.Schema({}) etc...

exampleSchema.plugin(uniqueValidator);

// module.exports = mongoose.model(...) etc....

3) 몽구스 방법

다음과 같은 방법을 사용할 findOneAndUpdate때이 구성 개체를 전달해야합니다.

{ runValidators: true, context: 'query' }

ie. User.findOneAndUpdate(
      { email: 'old-email@example.com' },
      { email: 'new-email@example.com' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }

4) 추가 옵션

  1. 대소 문자를 구분하지 않음

    스키마에서 uniqueCaseInsensitive 옵션을 사용하십시오.

    ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }

  2. 사용자 지정 오류 메시지

    ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });

이제 mongo를 다시 시작하거나 데이터베이스를 삭제하거나 색인을 생성하는 것에 대해 걱정하지 않고 고유 속성을 스키마에 추가 / 삭제할 수 있습니다.

주의 사항 (문서에서) :

문서가 데이터베이스에 있는지 확인하기 위해 비동기 작업에 의존하기 때문에 두 개의 쿼리가 동시에 실행되고 둘 다 0이 된 다음 둘 다 MongoDB에 삽입 될 수 있습니다.

컬렉션을 자동으로 잠 그거나 단일 연결을 강제하는 것 외에는 실제 솔루션이 없습니다.

대부분의 사용자에게 이것은 문제가되지 않지만 알아야 할 가장 중요한 경우입니다.


2

최신 답변 : mongodb를 다시 시작할 필요가 없습니다. colleciton에 이미 동일한 이름 인덱스가있는 경우 mongoose는 인덱스를 다시 만들지 않으므로 먼저 colleciton의 기존 인덱스를 삭제하고 이제 mongoose를 실행할 때 새 인덱스를 생성합니다. , 위의 프로세스가 내 문제를 해결했습니다.


1

색인을 삭제하여이 문제를 해결할 수도 있습니다.

collection users및 field 에서 고유 색인을 제거한다고 가정하고 다음을 username입력하십시오.

db.users.dropIndex('username_1');


1

테이블 / 컬렉션이 비어 있으면 필드에 대한 고유 인덱스를 만듭니다.

db.<collection_name>.createIndex({'field':1}, {unique: true})

테이블 / 컬렉션이 비어 있지 않은 경우 컬렉션을 삭제하고 인덱스를 만듭니다.

db.<collection_name>.drop()
db.<collection_name>.createIndex({'field':1}, {unique: true})

이제 mongoDB를 다시 시작하십시오.


1

스키마의 autoIndex가 true인지 확인하십시오. mongoose.connect 옵션을 사용할 때 false (기본값 true)로 설정 될 수 있습니다.


1

나는 한동안 같은 문제에 직면했고 많은 검색을했고 나를위한 해결책은 createIndexes() 기능이었습니다.

도움이 되었으면합니다.

그래서 코드는 그렇게 될 것입니다.

User = new Schema ({
   email: {type: String, unique: true}
});
User.createIndexes();

0

다음 autoIndex: false과 같은 연결 방법에서 옵션 을 사용하는 경우 :

mongoose.connect(CONNECTION_STRING, { autoIndex: false });

그것을 제거하십시오. 그래도 작동하지 않으면 이 스레드에서 제안한대로 mongodb다시 시작해보십시오 .


0

스키마를 다음과 같이 정의 할 수 있습니다.

User = new Schema ({
  email: {
      type: String,
      unique: true
  }
})

그러나 이미 문서가 있고 그 후에 사용자의 스키마를 변경하면 작동하지 않을 수 있습니다. 컬렉션을 삭제하지 않으려면이 사용자 컬렉션에 대한 이메일 색인을 생성 할 수 있습니다. 이 명령을 사용하여 이메일에 색인을 생성 할 수 있습니다.

db.User.createIndex({email:1},{unique: true})

또는 컬렉션을 삭제하고 사용자를 다시 추가 할 수 있습니다.
컬렉션 삭제의 경우 다음을 입력 할 수 있습니다.

db.User.drop()

0

이 문제가 발생했을 때 데이터베이스를 삭제하고 서버 (nodemon)를 여러 번 다시 시작했지만 어떤 트릭도 전혀 작동하지 않았습니다. Robo 3T를 통해 다음과 같은 해결 방법을 찾았습니다.

  1. Robo 3T에서 데이터베이스를 두 번 클릭하여 컬렉션을 엽니 다.
  2. 컬렉션을 열어 문제의 컬렉션을 표시합니다. 먼저 컬렉션이 비어 있는지 확인하십시오.
  3. Indexes 폴더를 마우스 오른쪽 버튼으로 클릭합니다. 기본적 _id_으로는 기본값으로 표시됩니다. 이제 색인 추가를 선택하십시오.
  4. email예를 들어 이메일 필드 의 이름을 선택하십시오.
  5. 키를 JSON으로 제공합니다. 예를 들면

    {
       "email": 1
    }
    
  6. 고유 확인란을 클릭하십시오.

  7. 저장

이렇게하면 MongoDB에 중복 된 이메일이 저장되지 않습니다.


여기 { "email": 1} 객체에서 1의 의미는 무엇입니까?
siluveru kiran kumar

0

컬렉션에 방금 고유 인덱스를 넣은 필드와 중복되지 않는지 확인하십시오.

그런 다음 앱을 다시 시작하십시오 (몽구스). 자동으로 색인 추가가 실패합니다.


0

컬렉션에서 모든 문서 제거 :

db.users.remove({})

그리고 다른 사람들이 언급했듯이 다시 시작하면 저에게 효과적이었습니다.


0

당신의 MongoDB를 서비스로 작동하면, 다음 변경을 수행 한 후이 서비스를 다시 시작해야 할 수도 있습니다 (이 찾는 쉬운 방법은 터미널을 통해 mongod.exe 파일을 시작하지 않고 데이터베이스에 연결할 필요가없는 경우입니다) 및 / 또는 데이터베이스를 완전히 삭제하십시오.

일부 사용자의 경우 단일 컬렉션을 삭제하는 것이 효과가 있기 때문에 매우 이상합니다. 그들 중 일부는 데이터베이스를 삭제해야했습니다. 그러나 그것들은 나를 위해 일하지 않았습니다. 데이터베이스를 삭제 한 다음 MongoDB 서버 서비스를 다시 시작했습니다.

Windows 검색 표시 줄에서 서비스 검색 서비스를 다시 시작한 다음 MongoDB 서비스를 찾으려면 두 번 클릭하여 연 다음 서비스를 중지하고 다시 시작합니다.

다른 방법이 당신에게 효과가 없다면, 나는 이것이 일을 할 것이라고 믿습니다.


0

제 경우에는 몽구스가 구식이었습니다. CMD에서 오래된 npm을 실행하여 확인했습니다. 그리고 업데이트 된 '몽구스'.

그것이 당신에게도 효과가 있는지 알려주십시오.


어떤 버전을 사용하고 계셨습니까?
Baboo_

0

응용 프로그램과 데이터베이스를 연결할 때 다음 옵션을 추가하십시오. "audoIndex : true"예를 들어 내 코드에서 다음을 수행했습니다.

const options = {
// your options go here
...
// this code is the solution
audoIndex: true
}
mongoose.connect(DB_URI, options);

또한 문제가있는 컬렉션을 삭제하고 제대로 작동하는지 확인하기 위해 다시 만들었습니다. 이 솔루션은 https://dev.to/emmysteven/solved-mongoose-unique-index-not-working-45d5 에서 찾았습니다. "MongoDB 다시 시작"과 같은 솔루션도 시도했지만 저에게 적합하지 않았습니다.

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