MongoDB에서 하위 문서(subdocument) 배열의 특정 인덱스에 해당하는 요소를 조건으로 검색하려면 $let 연산자와 $expr 연산자를 함께 사용하면 됩니다.
핵심 개념
- $let: 집계 표현식 내에서 임시 변수를 정의할 때 사용합니다.
- $expr: 쿼리 내부에서 집계 표현식(aggregation expression)을 사용할 수 있도록 해줍니다.
그럼 실제 예제를 통해 살펴보겠습니다. 먼저 컬렉션을 생성하고 문서를 삽입합니다.
> db.demo72.insertOne(
... {
... StudentDetails:[
... {
... Name: "Chris",
... Age: 21
... },
... {
... Name: "David",
... Age: 23
... },
... {
... Name: "Bob",
... Age: 20
... },
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e29b4ad71bf0181ecc42269")
}삽입된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 화면에 출력할 수 있습니다.
> db.demo72.find().pretty();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{
"_id" : ObjectId("5e29b4ad71bf0181ecc42269"),
"StudentDetails" : [
{
"Name" : "Chris",
"Age" : 21
},
{
"Name" : "David",
"Age" : 23
},
{
"Name" : "Bob",
"Age" : 20
}
]
}n번째 요소를 조회하는 쿼리 작성하기
이제 하위 문서 배열(StudentDetails)의 n번째 요소를 기준으로 검색하는 쿼리입니다. 아래 예제에서는 배열의 1번 인덱스(두 번째 요소)에 있는 학생의 이름이 "David"인지 확인합니다.
> db.demo72.find({
... $expr: {
... $let: {
... vars: { fst: { $arrayElemAt: [ "$StudentDetails", 1 ] } },
... in: { $eq: [ "$$fst.Name", "David" ] }
... }
... }
... })쿼리 구조를 살펴보면 다음과 같습니다.
$arrayElemAt: StudentDetails 배열에서 지정한 인덱스(여기서는 1)의 요소를 추출합니다.vars: 추출한 요소를 임시 변수fst에 저장합니다.in: 임시 변수의 Name 필드 값이 "David"와 일치하는지 비교합니다.
쿼리를 실행하면 다음과 같은 결과가 반환됩니다.
{
"_id" : ObjectId("5e29b4ad71bf0181ecc42269"), "StudentDetails" : [
{ "Name" : "Chris", "Age" : 21 }, { "Name" : "David", "Age" : 23 }, { "Name" : "Bob", "Age" : 20 }
]
}이처럼 $let과 $expr을 조합하면 하위 문서 배열의 특정 위치(변수 인덱스)에 있는 요소의 값을 조건으로 활용한 유연한 검색이 가능합니다. 인덱스 값을 동적으로 변경하고 싶다면 $arrayElemAt의 두 번째 인자에 변수나 다른 표현식을 전달하면 됩니다.