와일드카드 인덱스
MongoDB는 쿼리를 지원하기 위해 필드 또는 필드 세트에 인덱스를 생성하는 것을 지원합니다. MongoDB는 동적 스키마를 지원하므로 애플리케이션은 이름을 미리 알 수 없거나 임의적인 필드를 쿼리할 수 있습니다.
MongoDB 버전 4.2의 새로운 기능
MongoDB 4.2에는 알 수 없거나 임의의 필드에 대한 쿼리를 지원하기 위한 와일드카드 인덱스가 도입되었습니다.
userMetadata
필드 아래에서 사용자 정의 데이터를 캡처하고 해당 데이터에 대한 쿼리를 지원하는 애플리케이션을 생각해 보세요.
{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } } { "userMetadata" : { "dislikes" : "pickles" } } { "userMetadata" : { "age" : 45 } } { "userMetadata" : "inactive" }
관리자는 userMetadata
의 모든 하위 필드에 대한 쿼리를 지원하는 인덱스를 만들고자 합니다.
userMetadata
에 대한 와일드카드 인덱스는 userMetadata
, userMetadata.likes
, userMetadata.dislikes
및 userMetadata.age
에 대한 단일 필드 쿼리를 지원할 수 있습니다.
db.userData.createIndex( { "userMetadata.$**" : 1 } )
인덱스는 다음 쿼리를 지원할 수 있습니다.
db.userData.find({ "userMetadata.likes" : "dogs" }) db.userData.find({ "userMetadata.dislikes" : "pickles" }) db.userData.find({ "userMetadata.age" : { $gt : 30 } }) db.userData.find({ "userMetadata" : "inactive" })
userMetadata
에 대한 와일드카드가 아닌 인덱스는 userMetadata
값에 대한 쿼리만 지원할 수 있습니다.
중요
와일드카드 인덱스 만들기
중요
와일드카드 인덱스를 생성하려면 mongod
featureCompatibilityVersion 이 4.2
여야 합니다. fCV 설정에 대한 지침은 MongoDB 5.0 배포에서 기능 호환성 버전 설정을 참조하세요.
createIndexes
데이터베이스 명령 또는 해당 shell 헬퍼인 createIndex()
또는 createIndexes()
을 사용하여 와일드카드 인덱스를 생성할 수 있습니다.
필드에 와일드카드 인덱스 만들기
특정 필드의 값을 인덱싱하려면 다음을 수행합니다.
db.collection.createIndex( { "fieldA.$**" : 1 } )
이 와일드카드 인덱스를 사용하면 MongoDB는 fieldA
의 모든 값을 인덱싱합니다. 필드가 중첩된 문서 또는 배열인 경우 와일드카드 인덱스는 문서/배열에 재귀되어 문서/배열의 모든 필드에 대한 값을 저장합니다.
예를 들어 product_catalog
컬렉션의 문서에 product_attributes
필드가 포함될 수 있습니다. product_attributes
필드에는 내장된 문서 및 배열을 포함하여 임의의 중첩 필드가 포함될 수 있습니다.
{ "product_name" : "Spy Coat", "product_attributes" : { "material" : [ "Tweed", "Wool", "Leather" ] "size" : { "length" : 72, "units" : "inches" } } } { "product_name" : "Spy Pen", "product_attributes" : { "colors" : [ "Blue", "Black" ], "secret_feature" : { "name" : "laser", "power" : "1000", "units" : "watts", } } }
다음 작업은 product_attributes
필드에 와일드카드 인덱스를 생성합니다.
db.products_catalog.createIndex( { "product_attributes.$**" : 1 } )
와일드카드 인덱스는 product_attributes
또는 포함된 필드에 대한 임의의 단일 필드 쿼리를 지원할 수 있습니다.
db.products_catalog.find( { "product_attributes.size.length" : { $gt : 60 } } ) db.products_catalog.find( { "product_attributes.material" : "Leather" } ) db.products_catalog.find( { "product_attributes.secret_feature.name" : "laser" } )
참고
경로별 와일드카드 인덱스 구문은 wildcardProjection
옵션과 호환되지 않습니다. 자세한 내용은 wildcard
인덱스에 대한 옵션을 참조하세요.
모든 필드에 와일드카드 인덱스 만들기
문서의 모든 필드 값( _id
제외)을 인덱스하려면 "$**"
을(를) 인덱스 키로 지정합니다.
db.collection.createIndex( { "$**" : 1 } )
MongoDB는 이 와일드카드 인덱스를 사용하여 collection의 각 문서에 대한 모든 필드를 인덱싱합니다. 지정된 필드가 중첩된 문서 또는 배열인 경우 와일드카드 인덱스는 문서/배열에 재귀되어 문서/배열의 모든 필드에 대한 값을 저장합니다.
예제 는 모든 필드 경로에 와일드카드 인덱스 생성하기 항목을 참조하세요.
참고
와일드카드 인덱스는 기본적으로 _id
필드를 생략합니다. 와일드카드 인덱스에 _id
필드를 포함하려면 해당 필드를 wildcardProjection
문서에 명시적으로 포함해야 합니다. 자세한 내용 은 wildcard
인덱스 옵션을 참조하세요.
여러 특정 필드에 와일드카드 인덱스 만들기
문서에서 여러 특정 필드의 값을 인덱싱하려면 다음을 수행합니다.
db.collection.createIndex( { "$**" : 1 }, { "wildcardProjection" : { "fieldA" : 1, "fieldB.fieldC" : 1 } } )
MongoDB는 이 와일드카드 인덱스를 사용하여 collection의 각 문서에 지정된 필드에 대한 모든 값을 인덱싱합니다. 지정된 필드가 중첩된 문서 또는 배열인 경우 와일드카드 인덱스는 문서/배열에 재귀되어 문서/배열의 모든 필드에 대한 값을 저장합니다.
참고
와일드카드 인덱스는 _id
필드를 명시적으로 포함하는 경우를 제외하고 wildcardProjection
문서에서 포함 및 제외 문을 혼합하는 것을 지원하지 않습니다. wildcardProjection
에 대한 자세한 내용 은 wildcard
인덱스 옵션 을 참조 하세요 .
여러 특정 필드를 제외하는 와일드카드 인덱스 만들기
특정 필드 경로를 제외한 문서 내 모든 필드의 필드를 인덱싱하려면 다음을 수행합니다.
db.collection.createIndex( { "$**" : 1 }, { "wildcardProjection" : { "fieldA" : 0, "fieldB.fieldC" : 0 } } )
MongoDB는 이 와일드카드 인덱스를 사용하여 지정된 필드 경로를 제외한 컬렉션의 각 문서에 대한 모든 필드를 인덱싱합니다. 지정된 필드가 중첩된 문서 또는 배열인 경우 와일드카드 인덱스는 문서/배열에 재귀되어 문서/배열의 모든 필드에 대한 값을 저장합니다.
예시 는 와일드카드 인덱스 커버리지에서 특정 필드 생략을 참조하세요.
참고
와일드카드 인덱스는 _id
필드를 명시적으로 포함하는 경우를 제외하고 wildcardProjection
문서에서 포함 및 제외 문을 혼합하는 것을 지원하지 않습니다. wildcardProjection
에 대한 자세한 내용 은 wildcard
인덱스 옵션 을 참조 하세요 .
정규화된 와일드카드 인덱스 보기
MongoDB 5.0부터 와일드카드 인덱스는 생성 후 정규화되며, wildcardProjection 필드가 Express 이에 상응하는 필터를 하지 않는 한 동일한 키 패턴 을 사용하여 여러 와일드카드 인덱스를 생성할 수 있습니다.
예를 들어 와일드카드 인덱스를 생성합니다.
db.books.createIndex( { "$**" : 1 }, { wildcardProjection : {a: 1, "b.c": 1 } } )
db.collection.getIndexes()
메서드를 사용하여 인덱스를 확인합니다.
db.books.getIndexes()
결과는 정규화된 형식으로 표시됩니다.
{ v: 2, key: { _id: 1 }, name: '_id_' }, { v: 2, key: { '$**': 1 }, name: '$**_1', wildcardProjection: { a: true, b: { c: true }, _id: false } }
고려 사항
와일드카드 인덱스는 주어진 쿼리 조건자에서 최대 하나 의 필드를 지원할 수 있습니다. 와일드카드 인덱스 쿼리 지원에 대한 자세한 내용은 와일드카드 인덱스 쿼리/정렬 지원을 참조하세요.
와일드카드 인덱스를 생성하려면
mongod
featureCompatibilityVersion 이4.2
여야 합니다. fCV 설정에 대한 지침은 MongoDB 5.0 배포에서 기능 호환성 버전 설정을 참조하세요.와일드카드 인덱스는 기본적으로 _id 필드를 생략합니다. 와일드카드 인덱스에
_id
필드를 포함하려면 와일드카드 프로젝트 문서에 명시적으로 포함해야 합니다(예:{ "_id" : 1 }
).컬렉션에 여러 개의 와일드카드 인덱스를 만들 수 있습니다.
와일드카드 인덱스는 collection의 다른 인덱스와 동일한 필드를 포함할 수 있습니다.
와일드카드 인덱스는 희소 인덱스(sparse indexes) 로 분류되며, 인덱스된 필드가 있는 문서에 대한 항목만 포함합니다. 이는 인덱스 필드에 null 값이 포함되어 있더라도 마찬가지입니다.
행동
와일드카드 인덱스는 객체(예: 내장된 문서) 또는 배열인 필드를 인덱싱할 때 특정 동작을 합니다.
필드가 객체인 경우 와일드카드 인덱스는 객체로 내려가 그 내용을 인덱싱합니다. 와일드카드 인덱스는 발견되는 추가로 내장된 문서로 계속 내려갑니다.
필드가 배열인 경우 와일드카드 인덱스는 배열을 순회하고 각 요소를 인덱싱합니다.
배열의 요소가 객체인 경우 와일드카드 인덱스는 위에서 설명한 대로 객체로 내려가 해당 내용을 인덱싱합니다.
요소가 배열, 즉 상위 배열 내에 직접 포함된 배열인 경우 와일드카드 인덱스는 포함된 배열을 순회하지 않고 전체 배열을 단일 값으로 인덱싱합니다.
다른 모든 필드의 경우 기본(비객체/배열) 값을 인덱스에 기록합니다.
와일드카드 인덱스는 기본 값(즉, 객체나 배열이 아닌 필드)에 도달할 때까지 추가로 중첩된 객체 또는 배열을 계속 순회합니다. 그런 다음 해당 필드의 전체 경로와 함께 이 기본 값을 인덱싱합니다.
예를 들어 다음 문서를 살펴보세요.
{ "parentField" : { "nestedField" : "nestedValue", "nestedObject" : { "deeplyNestedField" : "deeplyNestedValue" }, "nestedArray" : [ "nestedArrayElementOne", [ "nestedArrayElementTwo" ] ] } }
parentField
가 포함된 와일드카드 인덱스는 다음 항목을 기록합니다.
"parentField.nestedField" : "nestedValue"
"parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"
"parentField.nestedArray" : "nestedArrayElementOne"
"parentField.nestedArray" : ["nestedArrayElementTwo"]
parentField.nestedArray
의 레코드에는 각 요소의 배열 위치가 포함되어 있지 않습니다. 와일드카드 인덱스는 요소를 인덱스에 기록할 때 배열 요소 위치를 무시합니다. 와일드카드 인덱스는 명시적 배열 인덱스를 포함하는 쿼리를 계속 지원할 수 있습니다. 자세한 내용 은 명시적 배열 인덱스를 사용한 쿼리를 참조하세요.
중첩된 객체를 사용한 와일드카드 인덱스 동작에 대한 자세한 내용은 중첩된 객체를 참조하세요 .
중첩 배열을 사용한 와일드카드 인덱스 동작에 대한 자세한 내용은 중첩 배열을 참조하세요 .
중첩된 객체
와일드카드 인덱스는 중첩된 객체를 만나면 객체로 내려가 내용을 인덱싱합니다. 예를 들면 다음과 같습니다.
{ "parentField" : { "nestedField" : "nestedValue", "nestedArray" : ["nestedElement"] "nestedObject" : { "deeplyNestedField" : "deeplyNestedValue" } } }
parentField
가 포함된 와일드카드 인덱스는 객체로 내려가 해당 콘텐츠를 탐색하고 인덱싱합니다.
자체가 객체인 각 필드(즉, 내장된 문서)에 대해 객체로 내려가서 해당 내용을 인덱싱합니다.
배열인 각 필드에 대해 배열을 순회하고 해당 내용을 인덱싱합니다.
다른 모든 필드의 경우 기본(비객체/배열) 값을 인덱스에 기록합니다.
와일드카드 인덱스는 기본 값(즉, 객체나 배열이 아닌 필드)에 도달할 때까지 추가로 중첩된 객체 또는 배열을 계속 순회합니다. 그런 다음 해당 필드의 전체 경로와 함께 이 기본 값을 인덱싱합니다.
샘플 문서가 주어지면 와일드카드 인덱스는 다음 기록을 인덱스에 추가합니다.
"parentField.nestedField" : "nestedValue"
"parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"
"parentField.nestedArray" : "nestedElement"
중첩 배열을 사용한 와일드카드 인덱스 동작에 대한 자세한 내용은 중첩 배열을 참조하세요 .
중첩 배열
와일드카드 인덱스는 중첩 배열을 발견하면 배열을 탐색하여 해당 요소를 인덱싱하려고 시도합니다. 배열 자체가 상위 배열(예: 내장된 배열)의 요소인 경우 와일드카드 인덱스는 대신 배열의 내용을 탐색하는 대신 전체 배열을 값으로 기록합니다. 예를 들면 다음과 같습니다.
{ "parentArray" : [ "arrayElementOne", [ "embeddedArrayElement" ], "nestedObject" : { "nestedArray" : [ "nestedArrayElementOne", "nestedArrayElementTwo" ] } ] }
parentArray
가 포함된 와일드카드 인덱스는 배열로 내려가 해당 내용을 탐색하고 인덱싱합니다.
배열인 각 요소(예: 내장된 배열)에 대해 전체 배열을 값으로 인덱스합니다.
객체인 각 요소에 대해 객체로 내려가 해당 내용을 탐색하고 인덱싱합니다.
다른 모든 필드의 경우 기본(비객체/배열) 값을 인덱스에 기록합니다.
와일드카드 인덱스는 기본 값(즉, 객체나 배열이 아닌 필드)에 도달할 때까지 추가로 중첩된 객체 또는 배열을 계속 순회합니다. 그런 다음 해당 필드의 전체 경로와 함께 이 기본 값을 인덱싱합니다.
샘플 문서가 주어지면 와일드카드 인덱스는 다음 기록을 인덱스에 추가합니다.
"parentArray" : "arrayElementOne"
"parentArray" : ["embeddedArrayElement"]
"parentArray.nestedObject.nestedArray" : "nestedArrayElementOne"
"parentArray.nestedObject.nestedArray" : "nestedArrayElementTwo"
parentField.nestedArray
의 레코드에는 각 요소의 배열 위치가 포함되어 있지 않습니다. 와일드카드 인덱스는 요소를 인덱스에 기록할 때 배열 요소 위치를 무시합니다. 와일드카드 인덱스는 명시적 배열 인덱스를 포함하는 쿼리를 계속 지원할 수 있습니다. 자세한 내용 은 명시적 배열 인덱스를 사용한 쿼리를 참조하세요.
인덱스 표시
MongoDB 5.0.16 부터 wildcardProjection
필드는 제출된 형식으로 인덱스 프로젝션을 저장합니다. 이전 버전의 서버에서는 프로젝션을 정규화된 형식으로 저장했을 수 있습니다.
서버는 인덱스를 동일한 방식으로 사용하지만 listIndexes
및 db.collection.getIndexes()
명령의 출력에 차이가 있을 수 있습니다.
제한 사항
와일드카드 인덱스를 사용하여 collection을 샤딩할 수 없습니다. 샤딩하려는 필드에 와일드카드가 아닌 인덱스를 생성합니다. 샤드 키 선택에 대한 자세한 내용은 샤드 키를 참조하세요 .
복합 인덱스 는 생성할 수 없습니다.
와일드카드 인덱스에는 다음 속성을 지정할 수 없습니다.
와일드카드 구문을 사용하여 다음 인덱스 유형을 생성할 수 없습니다.
중요
와일드카드 인덱스는 와일드카드 텍스트 인덱스와 구별되며 호환되지 않습니다. 와일드카드 인덱스는 $text
연산자를 사용하는 쿼리를 지원할 수 없습니다.
와일드카드 인덱스 생성 제한에 대한 전체 문서는 호환되지 않는 인덱스 유형 또는 속성을 참조하세요.
와일드카드 인덱스 쿼리/정렬 지원
지원되는 쿼리
와일드카드 인덱스는 다음이 모두 참인 경우에만 해당 쿼리 를 지원할 수 있습니다.
쿼리 플래너는 쿼리 조건자를 충족하기 위해 와일드카드 인덱스를 선택합니다.
쿼리 조건자는 와일드카드 인덱스가 적용되는 필드를 정확히 하나만 지정합니다.
프로젝션은
_id
를 명시적으로 제외하고 쿼리 필드 만 포함합니다.지정된 쿼리 필드는 절대 배열이 아닙니다.
employees
collection에 다음과 같은 와일드카드 인덱스가 있다고 가정해 봅시다.
db.products.createIndex( { "$**" : 1 } )
다음 작업은 단일 필드 lastName
에 대해 쿼리하고 결과 문서에서 다른 모든 필드를 프로젝트합니다.
db.products.find( { "lastName" : "Doe" }, { "_id" : 0, "lastName" : 1 } )
지정된 lastName
가 배열이 아니라는 가정 하에 MongoDB는 $**
와일드카드 인덱스를 사용하여 해당 쿼리를 지원할 수 있습니다.
다중 필드 쿼리 조건자
와일드카드 인덱스는 최대 하나 의 쿼리 조건자 필드를 지원할 수 있습니다. 즉:
MongoDB는 와일드카드가 아닌 인덱스를 사용하여 쿼리 조건자의 한 부분을 충족하고 와일드카드 인덱스를 사용하여 다른 부분을 충족할 수 없습니다.
MongoDB는 하나의 와일드카드 인덱스를 사용하여 쿼리 술어의 한 부분을 충족하고 다른 와일드카드 인덱스를 사용하여 다른 부분을 충족할 수 없습니다.
단일 와일드카드 인덱스가 여러 쿼리 필드를 지원할 수 있더라도 MongoDB는 와일드카드 인덱스를 사용하여 쿼리 필드 중 하나만 지원할 수 있습니다. 나머지 모든 필드는 인덱스 없이 해결됩니다.
그러나 MongoDB는 쿼리 $or
또는 애그리게이션 $or
연산자의 각 독립적인 인수를 충족하기 위해 동일한 와일드카드 인덱스를 사용할 수 있습니다.
정렬을 사용한 쿼리
MongoDB는 다음 사항이 모두 참인 경우에만 를 충족하기 위해 와일드카드 인덱스를 사용할 수 있습니다. sort()
쿼리 플래너는 쿼리 조건자를 충족하기 위해 와일드카드 인덱스를 선택합니다.
sort()
는 쿼리 조건자 필드 만 지정합니다.지정된 필드는 배열이 아닙니다.
위의 조건이 충족되지 않으면 MongoDB는 정렬에 와일드카드 인덱스를 사용할 수 없습니다. MongoDB는 쿼리 조건자의 인덱스와 다른 인덱스가 필요한 sort()
작업을 지원하지 않습니다. 자세한 내용은 인덱스 교차 및 정렬을 참조하세요.
products
collection에 다음과 같은 와일드카드 인덱스가 있다고 가정해 봅시다.
db.products.createIndex( { "product_attributes.$**" : 1 } )
다음 작업은 단일 필드 product_attributes.price
를 쿼리하고 동일한 필드를 정렬합니다.
db.products.find( { "product_attributes.price" : { $gt : 10.00 } }, ).sort( { "product_attributes.price" : 1 } )
지정된 price
가 배열이 아니라고 가정하면 MongoDB는 product_attributes.$**
와일드카드 인덱스를 사용하여 find()
및 sort()
을 모두 충족할 수 있습니다.
지원되지 않는 쿼리 패턴
와일드카드 인덱스는 다음 쿼리 패턴을 지원할 수 없습니다 .
필드가 존재하지 않는지 확인하는 쿼리
필드가 문서 또는 배열과 같은지 확인하는 쿼리
필드가 null과 같은지 확인하는 쿼리
자세한 내용은 지원되지 않는 쿼리 및 애그리게이션 패턴을 참조하세요.
명시적 배열 인덱스가 있는 쿼리
MongoDB 와일드카드 인덱스는 인덱싱 중에 배열에 지정된 요소의 배열 위치를 기록하지 않습니다. 그러나 MongoDB는 하나 이상의 명시적 배열 인덱스(예: parentArray.0.nestedArray.0
)가 있는 필드 경로를 포함하는 쿼리에 답변하기 위해 와일드카드 인덱스를 선택할 수 있습니다. 연속된 각 중첩 배열에 대한 인덱스 경계를 정의하는 것이 점점 더 복잡해지기 때문에 MongoDB는 경로에 8
개 이상의 명시적 배열 인덱스가 포함되어 있는 경우 쿼리에서 지정된 필드 경로에 응답하는 데 와일드카드 인덱스를 고려하지 않습니다. MongoDB는 여전히 쿼리의 다른 필드 경로에 응답하기 위해 와일드카드 인덱스를 고려할 수 있습니다.
예를 들면 다음과 같습니다.
{ "parentObject" : { "nestedArray" : [ "elementOne", { "deeplyNestedArray" : [ "elementTwo" ] } ] } }
MongoDB는 다음 쿼리를 충족하기 위해 parentObject
가 포함된 와일드카드 인덱스를 선택할 수 있습니다.
"parentObject.nestedArray.0" : "elementOne"
"parentObject.nestedArray.1.deeplyNestedArray.0" : "elementTwo"
쿼리 조건자의 지정된 필드 경로가 8개 이상의 명시적 배열 인덱스를 지정하는 경우 MongoDB는 해당 필드 경로에 응답할 때 와일드카드 인덱스를 고려하지 않습니다. 대신 MongoDB는 쿼리에 답변하기 위해 다른 적합한 인덱스를 선택 하거나 collection 스캔을 수행합니다.
와일드카드 인덱스 자체는 문서를 인덱싱하는 동안 문서를 탐색하는 깊이에 제한이 없습니다. 이 제한은 정확한 배열 인덱스를 명시적으로 지정하는 쿼리에만 적용됩니다. 명시적인 배열 인덱스 없이 동일한 쿼리를 실행함으로써 MongoDB는 와일드카드 인덱스를 선택하여 쿼리에 답변할 수 있습니다.
"parentObject.nestedArray" : "elementOne"
"parentObject.nestedArray.deeplyNestedArray" : "elementTwo"