MongoDB에서 배열(array) 내부에 특정 조건과 일치하는 객체가 몇 개 포함되어 있는지를 기준으로 문서를 조회해야 하는 경우가 있습니다. 이 글에서는 $where 연산자와 JavaScript 함수를 활용해 이러한 작업을 수행하는 방법을 예제와 함께 자세히 살펴보겠습니다.
1. 샘플 컬렉션 생성
먼저 insertOne() 메서드를 사용하여 문서가 담긴 컬렉션을 생성합니다.
> db.demo694.insertOne(
... {
... "details" :
... [
... {
... "Name" : "Chris",
... Age:21
... },
... {
... "Name" : "David",
... Age:22
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5ea59279ece4e5779399c07f")
}
> db.demo694.insertOne(
... {
... "details" :
... [
... {
... "Name" : "Bob",
... Age:21
... },
... {
... "Name" : "Mike",
... Age:23
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5ea5927aece4e5779399c080")
}
> db.demo694.insertOne(
... {
... "details" :
... [
... {
... "Name" : "Chris",
... Age:21
... },
... {
... "Name" : "Carol",
... Age:22
... }
... ]
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5ea5927aece4e5779399c081")
}
2. 전체 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.demo694.find();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5ea59279ece4e5779399c07f"), "details" : [ { "Name" : "Chris", "Age" : 21 }, { "Name" : "David", "Age" : 22 } ] }
{ "_id" : ObjectId("5ea5927aece4e5779399c080"), "details" : [ { "Name" : "Bob", "Age" : 21 }, { "Name" : "Mike", "Age" : 23 } ] }
{ "_id" : ObjectId("5ea5927aece4e5779399c081"), "details" : [ { "Name" : "Chris", "Age" : 21 }, { "Name" : "Carol", "Age" : 22 } ] }
3. 배열 내 일치 객체의 개수를 기준으로 문서 조회하기
다음은 배열 내에서 조건과 일치하는 객체의 개수를 기준으로 MongoDB에서 문서를 찾는 쿼리입니다. 여기서는 $where 연산자와 함께 JavaScript 함수를 정의하여, Name이 "Chris"이고 Age가 21인 객체가 details 배열 안에 최소 1개 이상 포함된 문서만 필터링합니다.
> nameChrisAge21= function () {
... var inc = 0;
... this.details.forEach(function (d) {
... if (d.Name == "Chris" && d.Age == 21) {
... inc= inc + 1;
... }
... });
... if (inc >= 1) {
... return true;
... }
... }
function () {
var inc = 0;
this.details.forEach(function (d) {
if (d.Name == "Chris" && d.Age == 21) {
inc= inc + 1;
}
});
if (inc >= 1) {
return true;
}
}
> db.demo694.find({$where:nameChrisAge21});
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5ea59279ece4e5779399c07f"), "details" : [ { "Name" : "Chris", "Age" : 21 }, { "Name" : "David", "Age" : 22 } ] }
{ "_id" : ObjectId("5ea5927aece4e5779399c081"), "details" : [ { "Name" : "Chris", "Age" : 21 }, { "Name" : "Carol", "Age" : 22 } ] }
결과를 보면 첫 번째 문서와 세 번째 문서만 반환된 것을 확인할 수 있습니다. 두 문서 모두 details 배열에 "Chris"(나이 21) 객체가 포함되어 있어 조건을 충족하기 때문입니다.
참고 사항
$where 연산자는 컬렉션의 각 문서에 대해 JavaScript 코드를 실행하는 방식으로 동작합니다. 이로 인해 실행 속도가 느려질 수 있고 인덱스를 활용할 수 없다는 단점이 있습니다. 따라서 대량의 데이터를 다루는 운영 환경에서는 집계 파이프라인(aggregation pipeline)의 $match 단계와 $expr, $filter, $size 연산자를 조합해 배열 요소 개수를 계산하는 방식을 사용하는 것이 더 효율적입니다. 소규모 데이터나 복잡한 조건이 필요한 임시 조회에는 $where 방식이 유용하게 활용될 수 있습니다.