it-source

MongoDB는 $exists 연산자로 필드의 존재를 확인할 때 인덱스를 사용할 수 있습니까?

criticalcode 2023. 7. 15. 10:14
반응형

MongoDB는 $exists 연산자로 필드의 존재를 확인할 때 인덱스를 사용할 수 있습니까?

데이터가 있는 경우users다음과 같은 컬렉션:

{ name: '...', 
  email: '...', 
  ...,
  photos: {
     123: { url: '...', title: '...', ... },
     456: { url: '...', title: '...', ... },
     ...
  }
} 

그리고 어떤 사용자가 사진 ID 127을 소유하고 있는지 알고 싶으며, 다음과 같은 질문을 사용합니다.

db.users.find( {'photos.127': {'$exists' => true} } );

시도해봤지만 MongoDB가 이 쿼리에 인덱스를 사용하도록 하는 것은 불가능할 것 같습니다.제가 시도한 지수는 다음과 같습니다.db.users.ensureIndex({photos:1});그리고 제가 사용했을 때explain()mongo는 BasicCursor(즉, 인덱스가 사용되지 않음)를 사용하고 있다고 말했습니다.

mongo가 이 쿼리에 사용할 인덱스를 만들 수 있습니까?

업데이트됨:

보이다$exists쿼리가 이제 이러한 티켓을 기반으로 인덱스를 올바르게 사용함 $valid 쿼리는 인덱스를 사용해야 하며 {$valid:false}은(는) 인덱스를 사용하지 않습니다.

이전 답변:

아니요, mongodb에게 기존 쿼리에 인덱스를 사용하도록 지시할 방법이 없습니다.인덱싱은 데이터와 완전히 관련되어 있습니다.$exists는 키(필드)에만 관련되므로 인덱스에 사용할 수 없습니다.

$filename은 지정된 키(또는 필드)가 문서에 존재하는지 여부만 확인합니다.

$208은 인덱스를 사용하지 않지만 데이터 구조를 다음으로 변경할 수 있습니다.

photos: [
     {id:123, url: '...', title: '...', ... },
     {id:456, url: '...', title: '...', ... },
     ...
  ]

그런 다음 사용합니다.

db.users.ensureIndex({photos.id:1}) 

사진 ID에 대한 인덱스를 만듭니다.

제가 틀린 것 같습니다. 사실 $exists 쿼리에서 인덱스를 사용하도록 강제할 수 있습니다.위의 구조를 사용하여 계속 진행해 보겠습니다. 하지만 귀하의 사진 ID는 확실히 포함되어 있지 않습니다. 즉, 일부 문서는 'ID' 키를 가지고 있고 일부 문서는 그렇지 않습니다.그런 다음 해당 인덱스에 스파스 인덱스를 생성할 수 있습니다.

db.users.ensureIndex({'photos.id': 1}, {'sparse': true})

그런 다음 다음과 같이 질문합니다.

db.users.find({'photos.id': {$exists: true}}).hint({'photos.id': 1})

쿼리가 인덱스를 사용하고 있는지 확인하기 위해 설명을 추가할 수 있습니다.다음은 제 결과입니다. 제 컬렉션의 모바일 키는 귀하의 photos.id 와 비슷합니다.

> db.test.count()
50000
> db.test.find({'mobile': {$exists: true}}).hint({'mobile': 1}).explain()
{
        "cursor" : "BtreeCursor mobile_1",
        "nscanned" : 49999,
        "nscannedObjects" : 49999,
        "n" : 49999,
        "millis" : 138,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
                "mobile" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        }
}

> db.test.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "ns" : "test.test",
                "name" : "_id_"
        },
        {
                "v" : 1,
                "key" : {
                        "mobile" : 1
                },
                "ns" : "test.test",
                "name" : "mobile_1",
                "sparse" : true,
                "background" : true
        }
]

도움이 되길 바랍니다!

MongoDB 2.0 이후 $exists쿼리는 인덱스를 사용해야 합니다.불행하게도 이 수정은 최신 버전에서 사라졌고 MongoDB 2.5에서 수정될 것입니다.

2022년 6월 현재 이 지수는 다음에 사용할 수 없습니다.${exists: true}case 및 는 다른 사례의 절반에 대해서만 부분적으로만 사용할 수 있습니다.MongoDB 인덱스에 대한 주요(IMO) 설계 버그가 있어 아직까지 사람들이 잘 알지 못하는 경우가 있어 해결책을 제시하여 이 답변을 게시합니다.

문제는 MongoDB가 존재하지 않는 필드를 다음과 같이 인덱싱한다는 것입니다.null그리고 이 필드들은 와 구별할 수 없습니다.null지수 관점에서 s.게다가 JS 유추와 관련된 약간의 혼란이 있습니다.undefined === null이지만 거이지입니다.undefined == null사실입니다.즉, 다음과 같습니다.

  • 을 할 때{$exists: false}인덱스를 사용할 수 있습니다.null 값과 존재하지 않는 값이 모두 인덱스에서 스캔되고 문서가 가져오고 null과 동일한 값이 필터링됩니다.해당 MongoDB 단계:[null, null] IXSCAN그리고.FETCH with {"$not" : {$exists: true}} filter.
  • 을 할 때{field: null}인덱스를 사용할 수 있습니다.그러기 위해서는 인덱스 스캔만 하면 됩니다.MongoDB는 그것을 다음과 같이 해석합니다.{field: { $eq: null }}역사적인 이유로 Mongo는 더 이상 사용되지 않는 것을 찾기도 합니다.undefined 유값/형:[undefined, undefined]U[null, null] IXSCANIMO는 평등을 가치 평등으로 해석하고 결과에 존재하지 않는 필드를 포함하지 않는 것이 훨씬 논리적일 것입니다.하지만 그것은 사실입니다.
  • null과 .field: {$type: "null"}인덱스를 사용할 수 있습니다.첫 번째 경우와 마찬가지로 단계는 다음과 같습니다.[null, null] IXSCAN그리고.FETCH with {'$type': [10]} filter필드가 없는 값은 불필요하게 가져온 다음 필터링됩니다.
  • 모든 기존 값을 검색해야 하는 경우(예: 값이 있는 값 포함)null그러면 당신은 불운합니다.검색 쿼리는 다음과 같습니다.{field: {$exists: true}}인덱스를 사용할 수 없습니다.mongo가 인덱스를 사용하고 있다면 다음과 같이 인덱스된 값을 포함할 것입니다.null필드가 null인 문서를 포함하고 나중에 존재하지 않는 값을 필터링합니다.따라서 전체 인덱스가 필요하므로 전체 수집 검색이 더 효율적입니다.Mongo 단계계:COLLSCAN with { '$exists': true } filter.
  • 다음과 같은 값 없이 살 수 있는 경우null 즉, 포지않됩니다아도하를 포함하지 않아도 .$type: null결과에서 인덱스를 사용할 수 있습니다.필드 유형이 e.g.인 경우ObjectId를 검색할 수 있습니다.{field: {$type: "object"}}: 유형목록목:{field: {$type: ["number", "object"]}}아니면 그냥{field: {$ne: "null"}}후자는 제외할 것입니다.null그리고.undefined유형을 입력합니다.Mongo 단계는 다음과 같습니다.
    • [{},[]) IXSCAN그리고.FETCH
    • '[nan.0, inf.0]U[{}, [])'그리고.FETCH
    • [MinKey, undefined)U(null, MaxKey] IXSCAN그리고.FETCH.

2014년 2월에 접수된 문제가 있습니다: https://jira.mongodb.org/browse/SERVER-12869 .안타깝게도 MongoDB는 아직 이 문제의 우선순위를 정하지도 않았고, 공식 문서에도 이 문제를 반영하지도 않았습니다.

2023년 2월 현재 최신 변경 사항과 함께 여기에 게시 - 인덱스와 함께 $209를 사용하려면 여기 를 참조하는 것이 좋습니다. https://www.mongodb.com/docs/manual/reference/operator/query/exists/

{$exists: true} 쿼리에 인덱스를 사용하려면 스파스 인덱스를 사용하는 것이 가장 좋습니다.

언급URL : https://stackoverflow.com/questions/8176310/can-mongodb-use-an-index-when-checking-for-existence-of-a-field-with-exists-ope

반응형