IT story

mongoDB / mongoose : null이 아닌 경우 고유

hot-time 2020. 9. 13. 11:47
반응형

mongoDB / mongoose : null이 아닌 경우 고유


고유 컬렉션 항목을 강제하는 방법이 있지만 항목이 null이 아닌 경우에만 궁금합니다 . e 샘플 스키마 :

var UsersSchema = new Schema({
    name  : {type: String, trim: true, index: true, required: true},
    email : {type: String, trim: true, index: true, unique: true}
});

이 경우 'email'은 필수는 아니지만 'email'이 저장되어 있으면이 항목이 고유한지 확인하고 싶습니다 (데이터베이스 수준에서).

빈 항목은 'null'값을 가져 오는 것처럼 보이므로 이메일이없는 모든 항목은 '고유'옵션과 충돌합니다 (이메일이없는 다른 사용자가있는 경우).

지금은 응용 프로그램 수준에서 해결 중이지만 해당 db 쿼리를 저장하고 싶습니다.

고마워


MongoDB v1.8 +부터는 sparse인덱스를 정의 할 때 옵션을 true 로 설정하여 고유 한 값을 보장하지만 필드없이 여러 문서를 허용하는 원하는 동작을 얻을 수 있습니다 . 에서와 같이 :

email : {type: String, trim: true, index: true, unique: true, sparse: true}

또는 셸에서 :

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

독특한 스파 스 인덱스는 여전히 여러 문서를 허용하지 않습니다 emailA의 필드 null경우에만 여러 문서, 없는email 필드.

참조 http://docs.mongodb.org/manual/core/index-sparse/를


tl; dr

예, null고유 한 "실제"값을 적용하면서 필드가로 설정 되거나 정의되지 않은 여러 문서를 가질 수 있습니다.

요구 사항 :

  • MongoDB v3.2 이상.
  • 구체적인 값 유형을 미리 알고 있어야합니다 (예 : 항상 a string또는 object그렇지 않은 경우 null).

세부 사항에 관심이 없으면 implementation섹션 으로 건너 뛰어도됩니다 .

더 긴 버전

@Nolan의 답변을 보완하기 위해 MongoDB v3.2부터 필터 표현식과 함께 부분 고유 인덱스를 사용할 수 있습니다.

부분 필터 표현식에는 제한이 있습니다. 다음 만 포함 할 수 있습니다.

  • 등식 (예 : 필드 : 값 또는 $eq연산자 사용)
  • $exists: true 표현,
  • $gt, $gte, $lt, $lte표현,
  • $type 표현,
  • $and 최상위 수준에서만 연산자

이것은 사소한 표현을 {"yourField"{$ne: null}}사용할 수 없음을 의미합니다 .

그러나 필드가 항상 동일한 유형을 사용 한다고 가정하면 $type표현식을 사용할 수 있습니다 .

{ field: { $type: <BSON type number> | <String alias> } }

MongoDB v3.6은 배열로 전달할 수있는 여러 유형을 지정하기위한 지원을 추가했습니다.

{ field: { $type: [ <BSON type1> , <BSON type2>, ... ] } }

이는 값이 아닌 경우 여러 유형 중 하나가 될 수 있음을 의미합니다 null.

따라서 email아래 예제 필드가 중 하나 string또는 binary data을 허용하도록 허용하려면 적절한 $type표현식은 다음과 같습니다.

{email: {$type: ["string", "binData"]}}

이행

몽구스

몽구스 스키마에서 지정할 수 있습니다.

const UsersSchema = new Schema({
  name: {type: String, trim: true, index: true, required: true},
  email: {
    type: String, trim: true, index: {
      unique: true,
      partialFilterExpression: {email: {$type: "string"}}
    }
  }
});

또는 컬렉션에 직접 추가합니다 (기본 node.js 드라이버 사용) :

User.collection.createIndex("email", {
  unique: true,
  partialFilterExpression: {
    "email": {
      $type: "string"
    }
  }
});

네이티브 mongodb 드라이버

사용 collection.createIndex

db.collection('users').createIndex({
    "email": 1
  }, {
    unique: true,
    partialFilterExpression: {
      "email": {
        $type: "string"
      }
    }
  },
  function (err, results) {
    // ...
  }
);

mongodb 쉘

사용 db.collection.createIndex:

db.users.createIndex({
  "email": 1
}, {
  unique: true, 
  partialFilterExpression: {
    "email": {$type: "string"}
  }
})

이렇게하면 null이메일을 포함하거나 이메일 필드없이 여러 레코드를 삽입 할 수 있지만 동일한 이메일 문자열 은 삽입 할 수 없습니다.


이 주제를 연구하는 사람들에게 간단한 업데이트입니다.

선택한 답변이 작동하지만 대신 부분 색인 사용을 고려할 수 있습니다.

Changed in version 3.2: Starting in MongoDB 3.2, MongoDB provides the option to create partial indexes. Partial indexes offer a superset of the functionality of sparse indexes. If you are using MongoDB 3.2 or later, partial indexes should be preferred over sparse indexes.

More doco on partial indexes: https://docs.mongodb.com/manual/core/index-partial/


Actually, only first document where "email" as field does not exist will get save successfully. Subsequent saves where "email" is not present will fail while giving error ( see code snippet below). For the reason look at MongoDB official documentation with respect to Unique Indexes and Missing Keys here at http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes.

  // NOTE: Code to executed in mongo console.

  db.things.ensureIndex({firstname: 1}, {unique: true});
  db.things.save({lastname: "Smith"});

  // Next operation will fail because of the unique index on firstname.
  db.things.save({lastname: "Jones"});

By definition unique index can only allow one value to be stored only once. If you consider null as one such value it can only be inserted once! You are correct in your approach by ensuring and validating it at application level. That is how it can be done.

You may also like to read this http://www.mongodb.org/display/DOCS/Querying+and+nulls

참고URL : https://stackoverflow.com/questions/7955040/mongodb-mongoose-unique-if-not-null

반응형