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


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의 username및 email필드 모두에 고유 인덱스가 적용됩니다 . 건배.


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.