Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB에서 점(.)이 포함된 키를 가진 문서를 찾는 쿼리 방법

MongoDB에서 필드 이름에 점(.)이 포함된 경우, 일반적인 도트 표기법(dot notation)으로는 해당 필드에 접근하기 어렵습니다. 이럴 때 $addFields 연산자를 활용하면 됩니다. 내부적으로 $objectToArray를 사용해 데이터를 키(key)와 값(value) 형태의 배열로 변환한 뒤, $filter$indexOfBytes를 조합하여 키 안에 점이 포함되어 있는지 확인할 수 있습니다.

1. 샘플 컬렉션 생성하기

먼저 점이 포함된 키를 가진 문서들로 컬렉션을 생성해 보겠습니다.

> db.demo364.insertOne(
...   {
...      "details" : {
...         "details1.otherdetails.Name" : {"FirstName":"Chris" }
...      }
...   }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e57d485d0ada61456dc936d")
}
> db.demo364.insertOne(
...    {
...       "details" : {
...          "details1.otherdetails.Name" : {"FirstName":"David" }
...       }
...    }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e57d486d0ada61456dc936e")
}

2. 저장된 문서 확인하기

find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.

> db.demo364.find();

위 쿼리는 다음과 같은 결과를 출력합니다.

{ "_id" : ObjectId("5e57d485d0ada61456dc936d"), "details" : { "details1.otherdetails.Name" : { "FirstName" : "Chris" } } }
{ "_id" : ObjectId("5e57d486d0ada61456dc936e"), "details" : { "details1.otherdetails.Name" : { "FirstName" : "David" } } }

3. 점이 포함된 키를 찾는 집계 쿼리

다음은 키에 점이 포함된 레코드를 검색하는 집계(aggregation) 쿼리입니다.

> db.demo364.aggregate([
...    {
...       $addFields: {
...          result: {
...             $filter: {
...                input: { $objectToArray: "$details" },
...                cond: {
...                   $ne: [ { $indexOfBytes: [ "$$this.k", "." ] } , -1 ]
...                 }
...             }
...          }
...       }
...    },
...    {
...       $match: {
...          $expr: {
...             $ne: [ { $size: "$result" }, 0 ]
...          }
...       }
...    },
...    {
...       $project: {
...          result: 0
...       }
...    }
... ])

쿼리 동작 원리

이 쿼리가 어떻게 동작하는지 단계별로 살펴보겠습니다.

첫 번째 단계($addFields): $objectToArraydetails 객체를 { k: 키, v: 값 } 형태의 배열로 변환합니다. 이후 $filter가 각 요소를 순회하며 $indexOfBytes로 키($$this.k) 안에서 점(.)의 위치를 찾습니다. 점이 존재하면 -1이 아닌 값이 반환되므로, 해당 요소는 필터링 결과에 포함됩니다.

두 번째 단계($match): 임시로 만든 result 배열의 크기가 0이 아닌 문서, 즉 점이 포함된 키를 하나 이상 가진 문서만 남깁니다.

세 번째 단계($project): 불필요해진 result 필드를 결과에서 제거하여 원본 문서 형태 그대로 출력합니다.

실행 결과

위 쿼리를 실행하면 다음과 같이 키에 점이 포함된 두 개의 문서가 모두 조회됩니다.

{ "_id" : ObjectId("5e57d485d0ada61456dc936d"), "details" : { "details1.otherdetails.Name" : { "FirstName" : "Chris" } } }
{ "_id" : ObjectId("5e57d486d0ada61456dc936e"), "details" : { "details1.otherdetails.Name" : { "FirstName" : "David" } } }

참고 사항

MongoDB에서는 필드 이름에 점을 사용하는 것이 권장되지 않습니다. 점은 중첩 필드 경로를 나타내는 예약 문자이기 때문에, 점이 포함된 키는 일반적인 쿼리나 업데이트 작업에서 예상치 못한 동작을 유발할 수 있습니다. 따라서 이런 쿼리로 점이 포함된 키를 찾아낸 후에는, 데이터 마이그레이션을 통해 키 이름을 언더스코어(_) 같은 안전한 문자로 변경하는 것이 좋습니다.