MongoDB에서 배열 필드 안에 저장된 데이터 중 여러 조건을 동시에 만족하는 요소를 찾아야 할 때가 있습니다. 이럴 때는 aggregate() 메서드와 $elemMatch 연산자를 함께 사용하면 됩니다.
$elemMatch는 단순히 여러 필드 조건을 나열하는 것과 달리, 배열 내 하나의 요소가 모든 조건을 한 번에 충족하는지 검사한다는 점이 핵심입니다. 아래 예제를 통해 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성하기
먼저 직원 정보를 담은 배열(EmployeeDetails)을 포함하는 컬렉션을 만들어 보겠습니다. insertOne() 메서드로 두 개의 문서를 삽입합니다.
> db.demo84.insertOne({
... "EmployeeDetails": [
... { Name: 'John', Salary: 45000, isMarried: true },
... { Name: 'Chris', Salary: 50000, isMarried: false }
... ]
... });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2c0a3471bf0181ecc422a5")
}
> db.demo84.insertOne({
... "EmployeeDetails": [
... { Name: 'Sam', Salary: 56000, isMarried: false },
... { Name: 'Bob', Salary: 50000, isMarried: false }
... ]
... });
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2c0a4071bf0181ecc422a6")
}
2. find()로 전체 문서 확인하기
삽입된 문서들이 제대로 저장되었는지 find() 메서드로 확인합니다.
> db.demo84.find();
위 쿼리는 다음과 같은 결과를 출력합니다.
{
"_id" : ObjectId("5e2c0a3471bf0181ecc422a5"),
"EmployeeDetails" : [
{ "Name" : "John", "Salary" : 45000, "isMarried" : true },
{ "Name" : "Chris", "Salary" : 50000, "isMarried" : false }
]
}
{
"_id" : ObjectId("5e2c0a4071bf0181ecc422a6"),
"EmployeeDetails" : [
{ "Name" : "Sam", "Salary" : 56000, "isMarried" : false },
{ "Name" : "Bob", "Salary" : 50000, "isMarried" : false }
]
}
3. 배열 내 여러 조건을 일치시키는 쿼리 작성하기
이제 핵심인 aggregate() 쿼리입니다. $match 스테이지에서 $elemMatch를 사용하여 '이름이 Chris이면서 미혼(false)인 직원'을 포함한 문서만 조회해 보겠습니다.
> db.demo84.aggregate(
... { "$match": {
... "EmployeeDetails": {
... "$elemMatch": {
... "Name": "Chris",
... "isMarried": false
... }
... }
... }}
... );
쿼리 실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5e2c0a3471bf0181ecc422a5"),
"EmployeeDetails" : [
{ "Name" : "John", "Salary" : 45000, "isMarried" : true },
{ "Name" : "Chris", "Salary" : 50000, "isMarried" : false }
]
}
$elemMatch가 필요한 이유
만약 조건을 { "EmployeeDetails.Name": "Chris", "EmployeeDetails.isMarried": false }처럼 단순하게 나열하면, MongoDB는 서로 다른 배열 요소가 각각 조건을 만족해도 해당 문서를 반환할 수 있습니다. 반면 $elemMatch는 동일한 하나의 배열 요소가 모든 조건을 충족해야만 문서를 매칭하므로, 훨씬 정확한 조회가 가능합니다.
정리
- 배열 내부의 여러 기준을 동시에 일치시키려면
aggregate()의$match스테이지와$elemMatch를 사용합니다. $elemMatch는 하나의 배열 요소가 모든 조건을 만족하는 경우에만 매칭합니다.- 조회 성능과 정확도를 위해 배열 조건 검색 시에는
$elemMatch사용을 권장합니다.