code

Mongoose Unique 인덱스가 작동하지 않습니다!

starcafe 2023. 2. 22. 22:23
반응형

Mongoose Unique 인덱스가 작동하지 않습니다!

MongoDB가 인덱스를 기반으로 중복된 값을 검출하도록 하려고 합니다.MongoDB에서는 가능하다고 생각합니다만, Mongoose 포장지를 보면 파손된 것 같습니다.따라서 다음과 같은 경우:

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

같은 메일로 2명의 사용자를 저장할 수 있습니다.아뿔싸!

같은 문제가 여기에서도 나타나고 있습니다.https://github.com/LearnBoost/mongoose/issues/56, 하지만 이 스레드는 오래되어 아무 데도 연결되지 않습니다.

지금은 수동으로 DB에 전화를 걸어 사용자를 찾고 있습니다.그 통화는 「이메일」이 색인화되어 있기 때문에 비싸지 않다.그래도 네이티브하게 처리하면 좋을 것 같아요.

이에 대한 해결책을 가진 사람이 있나요?

어머! 몽고만 다시 시작하면 돼.

어머! 몽고만 다시 시작하면 돼.

또한 다음을 사용하여 재색인화:

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

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

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

이치노 때, 이 .email 회사의 to to our our to to 에 기입하다UserSchema사용자를 이미 DB에 추가한 후에도 중복된 전자 메일로 사용자를 저장할 수 있었습니다.했습니다.

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

에서 2) mongo shell 명령어를 합니다.db.users.createIndex({email: 1}, {unique: true})

순서 1에 대해서는, Mongo 의 메뉴얼로부터 다음의 점에 주의해 주세요.

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

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

나는 다음과 같은 일을 했다.

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

는 가했 the the the를 추가했다.Foo.createIndexes() BC.코드 실행 중에 다음과 같은 권장 해제 경고가 발생했습니다.

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

Foo.createIndexes()AFAIK는 비동기이지만 정상적으로 동작하고 있는 것 같습니다.


문제를 해결하기 위한 절차:

추가1 . 1unique: true속성으로 이동합니다.

let schema = new mongoose.Schema(
    {
        name: {
            type: String,
            unique: true,
            required: [true, "name required."],
        }
    }
);

module.exports = mongoose.model("role", schema);

예: 2. 컬렉션을 삭제합니다(예:role 줄 (마지막 줄)

  • 이 방법은 중복된 값이 이미 있는 경우 쉽게 수정할 수 있습니다.
  • 의 모든 에 중복된 할 수도 (「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」 「」).name상기의경우)를 참조)

Node합니다.Node.js 서버는 3. Node.js 를 합니다.mongoose★★★★★★★★★★★★★★★★★★.


여기 있는 다른 답들 중 몇 가지는 틀렸나요?

  • autoIndex은 「이렇게 하다」로 되어 있습니다.true

    • 필수가 아닙니다.기본적으로는 true 입니다.
  • db를 재시작합니다.

    • 필수는 아닙니다.Node.js 서버를 재부팅하기만 하면 됩니다.

  • 를 따르세요.in sequence
    • 놓친 게 있으면 두 번 해

이 동작은, Mongo 에 몇개의 복제를 남겼을 경우에도 발생합니다.Mongoose는 어플리케이션이 시작되면 Mongo에서 작성하려고 합니다.

이를 방지하기 위해 다음 방법으로 이 오류를 처리할 수 있습니다.

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

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

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

셸은 다음과 같이 응답합니다.

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

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

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

Write Result ({ "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\" }"
    }
})

매뉴얼에 따르면 https://docs.mongodb.com/v2.6/tutorial/modify-an-index/

기존 인덱스를 수정하려면 인덱스를 삭제하고 다시 생성해야 합니다.

Mongo를 재부팅하지 마십시오!

1 - 컬렉션을 드롭합니다.

db.users.drop()

2 - 표 재색인화

db.users.ensureIndex({email: 1, type: 1}, {unique: true})

프로그램레벨에서할 때 Mongoose에 .따라서 mongo CLI를 사용하여 데이터베이스 자체에서 고유한 인덱스를 적용하거나 mongoose에게 Mongoose에 대해 진지하게 생각하고 있음을 명시적으로 알리는 것이 좋습니다.uniqueUserSchema user음음음음음음음 user user user user user user user user user user user user user 。

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

양쪽에서 됩니다.username ★★★★★★★★★★★★★★★★★」email[ UserSchema ] [ [ [ [ 。★★★★★★ 。

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

  1. 컬렉션에 동일한 이름의 색인이 이미 있습니다.
  2. 컬렉션에 색인된 필드의 중복이 있는 문서가 이미 있습니다.

첫 번째 경우 인덱스를 에 나열하고 오래된 인덱스를 에 드롭합니다.Mongoose 응용 프로그램을 재시작하면 새 인덱스가 올바르게 추가됩니다.

두 번째 경우 Mongoose 응용 프로그램을 재시작하기 전에 중복 항목을 제거해야 합니다.

몽구스 검사기

이 플러그인 사용 방법:

1) npm install --save mongoose-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) mongoose 방법

like like like like like like like like like like like 등의 방법을 사용할 경우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. 대소문자를 구별하지 않다

    unique Case 사용스키마의 민감하지 않은 옵션

    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에 삽입할 수 있습니다.

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

대부분의 사용자에게 이는 문제가 되지 않지만 주의해야 할 가장 중요한 사례입니다.

최신 답변: mongodb를 재시작할 필요가 전혀 없습니다. coleciton이 이미 동일한 이름 인덱스를 가지고 있으면 mongoose는 인덱스를 다시 만들지 않으므로 먼저 coleciton의 기존 인덱스를 드롭하고 mongoose를 실행하면 새로운 인덱스를 생성할 수 있습니다. 위의 프로세스에서 문제가 해결되었습니다.

오래된 질문입니다만, 이 문제가 아직 남아 있는 사용자의 경우 인덱스를 제대로 적용하지 않았을 수 있습니다.

autoIndex 、 " to to to to to"로 설정되어 있습니다.false 중 은 """로 것입니다.true 이 인 "Default"로 .true되지 않습니다으로 「」, 「」, 「」, 「」를 호출하는 입니다.명시적으로 문의하는 것이 좋습니다.createIndexes이 경우 스키마에 정의된 대로 인덱스가 올바르게 생성됩니다.

이 때문에, 원래의 질문의 예의 구문은 다음과 같습니다.

const userSchema = new mongoose.Schema({
  email: { type: String, required: true, index: true, unique: true },
  // other fields
});

// methods, statics, hooks... etc

const User = mongoose.model("User", userSchema);

User.createIndexes();

module.exports = User;

재기동이나 플러그 인의 사용은 나에게 효과가 없었습니다.또한 mongo가 스스로 할 수 있다고 확신하는 것에 플러그 인을 사용하는 것은 조금 무리입니다.

여기 수정 사항이 있습니다. 연결 함수에서 이것을 옵션 객체에 추가합니다(2번째 매개 변수).

const options = {
  autoIndex: true, //this is the code I added that solved it all
}
mongoose.connect(process.env.MONGO_URI, options);

인덱스를 드롭하여 이 문제를 해결할 수도 있습니다.

를 들어,해 보겠습니다.users 필드 " " "username , , , , 라고 합니다.

db.users.dropIndex('username_1');

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

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

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

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

이제 mongoDB를 재시작합니다.

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

, 그은 ''가 아니었던가.createIndexes()★★★★★★ 。

도움이 됐으면 좋겠어요.

코드가 그렇게 될 거예요.

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

을 하고 있는 autoIndex: false하다

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

그것을 제거해 보세요.이 방법으로 동작하지 않는 경우는, 이 스레드에 제시된 수만큼, mongodb재기동해 주세요.

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

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

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

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

또는 컬렉션을 삭제하고 사용자를 다시 추가할 수도 있습니다.
collection ]에는[Dropping the collection]을 합니다.

db.User.drop()

이 문제가 발생했을 때 데이터베이스를 폐기하고 서버(노데몬)를 여러 번 재기동하려고 했지만 전혀 효과가 없었습니다.Robo 3T를 통해 다음과 같은 작업을 할 수 있었습니다.

  1. Robo 3T에서 데이터베이스를 두 번 클릭하여 컬렉션을 엽니다.
  2. 컬렉션을 열고 해당 컬렉션을 표시합니다.우선 컬렉션이 비어 있는지 확인합니다.
  3. 인덱스 폴더를 마우스 오른쪽 버튼으로 클릭합니다. 「」가 됩니다._id_디폴트로 합니다. Index [ Add Index ]를 합니다.
  4. 을 고르세요. 를 들어, 이름을 고르세요.email를 들어 [(이메일)]필드의 경우필드의 경우
  5. 키를 JSON으로 제공합니다.예를들면

    {
       "email": 1
    }
    
  6. [ Unique ]체크박스를 클릭합니다.

  7. 절약하다

그러면 중복된 이메일이 MongoDB에 저장되지 않습니다.

컬렉션에 고유 인덱스를 추가한 필드의 중복이 없는지 확인하십시오.

그럼 앱(mongoose)을 재시작하면 됩니다.인덱스 추가가 자동으로 실패합니다.

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

db.users.remove({})

그리고 다른 사람들이 말한 것처럼, 다시 시작하는 것은 나에게 효과가 있었다.

MongoDB가 서비스로 기능하는 경우(mongod를 시작하지 않고 데이터베이스에 연결할 필요가 없는 경우)exe file ver terminal)을 사용하여 변경 후 서비스를 재시작하거나 데이터베이스를 완전히 폐기해야 할 수 있습니다.

일부 사용자에게는 하나의 컬렉션을 폐기하는 것이 효과가 있었기 때문에 매우 이상합니다.그들 중 몇몇은 데이터베이스를 삭제해야 했다.하지만 그것들은 나에게 효과가 없었다.데이터베이스를 삭제하고 MongoDB Server 서비스를 재시작했습니다.

Windows 검색창에서 서비스 검색 서비스를 재시작하여 MongoDB 서비스를 찾으려면 두 번 클릭하여 열고 서비스를 중지한 후 다시 시작하십시오.

다른 방법이 통하지 않았다면 이것으로 충분하다고 생각합니다.

내 경우 몽구스는 구식이었다.CMD에서 npm olday를 실행하여 확인하고 'mongoose'를 업데이트했습니다.

당신에게도 그것이 효과가 있었는지 알려주세요.

데이터베이스를 응용 프로그램에 연결할 때 다음 옵션을 추가합니다. 예를 들어, 내 코드에 "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」등의 솔루션도 시험해 보았습니다만, 효과가 없었습니다.

제 경우 인덱스를 작성하려면 schema.index를 정의해야 합니다.Mongoose 매뉴얼인덱스 https://mongoosejs.com/docs/guide.html#indexes,를 확인해 주세요.

  • 스키마를 변경한 후에는 서버를 재시작하여 확인해야 합니다.

이제 아래 코드를 살펴보고 테스트해 보십시오.

const schemaUser = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
      index: true,
      unique: true,
      dropDups: true,
    },
    hash: String,
    created: {
      type: Date,
      default: Date.now,
    },
  },
  {
    autoCreate: true, // auto create collection
    autoIndex: true, // auto create indexes
  }
)
// define indexes to be create
schemaUser.index({ username: 1 })

const User = mongoose.model('Users', schemaUser)
const newUser = new Users({ username: 'wintzer' })
newUser.save(function (err) {
  if (err) console.log(err)
})

""를 언급해 주세요.useCreateIndex: true

mongoose.connect(url, {
  useNewUrlParser: true,
  useCreateIndex: true,
  useFindAndModify: false,
  useUnifiedTopology: true,
})

'unique: true' 또는 mongoose-unique-validator 플러그인을 사용할 필요가 없습니다.countDocuments()를 사용하는 유형 정의에 커스텀 비동기 검증()을 사용하면 됩니다.

스키마 내부...(Schema가 사용자 모델용이라고 가정)

email: {type: String, required: true, trim: true, lowercase: true, async validate(value) {
    const count = await mongoose.models.User.countDocuments({email: value});
    if (count > 0) {
        const existing = await  mongoose.models.User.findOne({email: value});
        if (!(existing._id.toString() === this._id.toString())) {
            throw new Error("Email not unique");
        }
    }
}}

데이터의 자동 인덱스를 지정하지 않았다면, 즉 고유성을 확인하는 것을 의미하며 mongoose는 그렇게 하지 않습니다.

데이터베이스에 접속할 때 간단하게 실현

mongoose.connect('connection url', {
    useUnifiedTopology: true,
    useNewUrlParser: true,
    useCreateIndex: true, //make this true
    autoIndex: true, //make this also true
})
.then(() => {
    console.log('Connected to mongoDB');
});

언급URL : https://stackoverflow.com/questions/5535610/mongoose-unique-index-not-working

반응형