source

null 값을 무시하는 mongoDB 3.2의 고유 인덱스

ittop 2023. 5. 27. 11:58
반응형

null 값을 무시하는 mongoDB 3.2의 고유 인덱스

고유 인덱스 필드의 null 값을 무시하고 partialFilterExpression을 기반으로 필터링된 문서를 무시하는 필드에 고유 인덱스를 추가합니다.

문제는 스파스 인덱스를 부분 인덱스와 함께 사용할 수 없다는 것입니다.

또한 고유 인덱스를 추가하면 인덱스 키 필드에 null 값이 추가되므로 PartialFilterExpression의 $exist 기준에 따라 문서를 무시할 수 없습니다.

MongoDB 3.2에서 이 상황을 피할 수 있습니까?

제가 해결책을 찾다가 찾지 못해서 이 답변을 추가합니다.이것은 이 질문에 정확하게 답하지 않을 수도 있고 그럴 수도 있지만, 저와 같은 많은 다른 사람들에게 도움이 될 것입니다.

예문.에 의경우가 null이라houseName그리고 그것은 유형입니다.string은 다음과 수 .

db.collectionName.createIndex(
   {name: 1, houseName: 1},
   {unique: true, partialFilterExpression: {houseName: {$type: "string"}}}
);

이는다무다니합시가 됩니다.null의 값houseName여전히 독특합니다.

예, MongoDB 3.2에서 부분 인덱스를 생성할 수 있습니다.

자세한 내용은 https://docs.mongodb.org/manual/core/index-partial/ #index-type-messages를 참조하십시오.

MongoDB는 희소 인덱스보다 부분 인덱스를 사용할 것을 권장합니다.부분 인덱스에 유리하도록 희소 인덱스를 삭제할 것을 제안합니다.

mongo:3.2에서 부분 인덱스를 생성할 수 있습니다.예를 들어 ipaddress가 ""일 수 있지만 "127.0.0.1"은 고유해야 합니다.솔루션은 다음과 같습니다.

db.collectionName.createIndex(
 {"ipaddress":1},
 {"unique":true, "partialIndexExpression":{"ipaddress":{"$gt":""}}})

그러면 ipaddress file의 "" 값은 무시되고 여전히 고유합니다.

"YourField" : {"$exists" : true, "$gt" : "0", "$type" : "string" } }

mongodb Compass에서 작성하려면 JSON으로 작성해야 합니다.

지원하는 다른 유형을 찾으려면 이 링크를 참조하십시오.

여기에 이미지 설명 입력

예, 부분 필터 식에 'not' 필터가 포함될 수 없는 문제일 수 있습니다.

이와 같은 인덱스에 대한 C# 솔루션에 관심이 있을 수 있는 사람들을 위해 예를 들어 보겠습니다.

우리는 '사용자' 개체를 가지고 있는데, 이 개체는 '의사' 개체와 일대일 '관계'를 가지고 있습니다.이 관계는 '사용자' 엔티티에서 필수가 아닌 null 가능 필드 'DoctorId'로 표시됩니다.즉, 주어진 '의사'를 한 번에 한 명의 '사용자'에만 연결할 수 있어야 한다는 요구사항이 있습니다.

따라서 다른 '사용자' 엔티티에 대해 이미 설정된 것과 동일한 GUID로 닥터Id를 설정하려고 할 때 예외를 발생시킬 수 있는 고유 인덱스가 필요합니다.동시에 많은 사용자에게 연결된 의사가 없으므로 'DoctorId' 필드에 여러 개의 'null' 항목이 허용되어야 합니다.

이러한 종류의 인덱스를 구축하는 솔루션은 다음과 같습니다.

var uniqueDoctorIdIndexDefinition = new IndexKeysDefinitionBuilder<User>()
    .Ascending(o => o.DoctorId);
var existsFilter = Builders<User>.Filter.Exists(o => o.DoctorId);
var notNullFilter = Builders<User>.Filter.Type(o => o.DoctorId, BsonType.String);
var andFilter = Builders<User>.Filter.And(existsFilter, notNullFilter);
var createIndexOptions = new CreateIndexOptions<User>
{
    Unique = true,
    Name = UniqueDoctorIdIndexName,
    PartialFilterExpression = andFilter,
};
var uniqueDoctorIdIndex = new CreateIndexModel<User>(
    uniqueDoctorIdIndexDefinition,
    createIndexOptions);

users.Indexes.CreateOne(uniqueDoctorIdIndex);

아마도 '사용자' 엔티티에 대한 설명에서 속성을 사용하여 'DoctorId' 필드의 BsonType을 직접 지정해야 합니다. 예를 들어, 다음과 같습니다.

[BsonRepresentation(BsonType.String)]
public Guid? DoctorId { get; set; }

저는 이 문제에 대해 더 능숙하고 콤팩트한 해결책이 있다고 확신하기 때문에, 누군가가 여기서 그것을 제안한다면 기쁠 것입니다.

다음은 mongoDB 부분 인덱스 문서에서 수정한 예제입니다.

db.contacts.createIndex(
   { email: 1 },
   { unique: true, partialFilterExpression: { email: { $exists: true } } }
)

중요한

부분 인덱스를 사용하려면 쿼리 조건의 일부로 필터 식(또는 필터 식의 하위 집합을 지정하는 수정된 필터 식)을 포함해야 합니다.

다음과 같은 쿼리를 볼 수 있습니다.

db.contacts.find({'email':'name@email.com'}).explain()

사용자가 지정하지 않더라도 인덱스 검색을 수행하고 있음을 나타냅니다.{$exists: true}필터에 전자 메일을 지정하여 partialFilterExpression의 하위 집합을 암시적으로 지정하는 것이기 때문입니다.

반면에 다음 쿼리는 수집 검색을 수행합니다.

db.contacts.find({email: {$exists: false}})

경고

신화적인 코더의 답변(현재 가장 투표율이 높은 답변)은 고유한 인덱스를 성공적으로 만들기 때문에 매우 오해의 소지가 있지만, 쿼리 플래너는 사용자가 추가하지 않는 한 일반적으로 작성한 인덱스를 사용할 수 없습니다.houseName: {$type: "string"}필터 표현식에 입력합니다.이로 인해 사용자가 인지하지 못할 수 있는 성능 비용이 발생할 수 있으며 향후 문제가 발생할 수 있습니다.

언급URL : https://stackoverflow.com/questions/35755628/unique-index-in-mongodb-3-2-ignoring-null-values

반응형