MongoDB에서 배열 필드가 특정 배열의 요소들로만 구성되어 있는지, 즉 제공된 배열의 어떤 조합이든 포함하는지 확인해야 하는 경우가 있습니다. 이럴 때는 $nin 연산자를 $elemMatch 및 $not 연산자와 함께 사용하면 됩니다.
테스트용 컬렉션 생성하기
개념을 쉽게 이해하기 위해 먼저 샘플 문서가 포함된 컬렉션을 생성해 보겠습니다. 아래 쿼리를 순서대로 실행하세요.
> db.combinationOfArrayDemo.insertOne({"StudentName":"Larry","StudentAge":21,"StudentFavouriteTechnicalSubject":["C","Java"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f77cc8d10a061296a3c58")
}
> db.combinationOfArrayDemo.insertOne({"StudentName":"Mike","StudentAge":23,"StudentFavouriteTechnicalSubject":["C++","Java"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f77dc8d10a061296a3c59")
}
> db.combinationOfArrayDemo.insertOne({"StudentName":"David","StudentAge":22,"StudentFavouriteTechnicalSubject":["Java"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f77f48d10a061296a3c5a")
}위 컬렉션에는 세 명의 학생 데이터가 저장되어 있습니다. Larry는 'C'와 'Java', Mike는 'C++'와 'Java', David는 'Java'를 좋아하는 기술 과목으로 가지고 있습니다.
저장된 문서 전체 조회하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.combinationOfArrayDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c7f77cc8d10a061296a3c58"),
"StudentName" : "Larry",
"StudentAge" : 21,
"StudentFavouriteTechnicalSubject" : [
"C",
"Java"
]
}
{
"_id" : ObjectId("5c7f77dc8d10a061296a3c59"),
"StudentName" : "Mike",
"StudentAge" : 23,
"StudentFavouriteTechnicalSubject" : [
"C++",
"Java"
]
}
{
"_id" : ObjectId("5c7f77f48d10a061296a3c5a"),
"StudentName" : "David",
"StudentAge" : 22,
"StudentFavouriteTechnicalSubject" : [
"Java"
]
}배열 조합 매칭 쿼리 작성하기
이제 핵심 부분입니다. MongoDB에서 제공된 배열(여기서는 ['C++', 'Java'])의 어떤 조합이든 포함하는 배열 필드를 매칭하는 쿼리는 다음과 같습니다.
> db.combinationOfArrayDemo.find({StudentFavouriteTechnicalSubject: {$not: {$elemMatch:
{$nin: ['C++', 'Java']}}}}).pretty();위 쿼리의 실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c7f77dc8d10a061296a3c59"),
"StudentName" : "Mike",
"StudentAge" : 23,
"StudentFavouriteTechnicalSubject" : [
"C++",
"Java"
]
}
{
"_id" : ObjectId("5c7f77f48d10a061296a3c5a"),
"StudentName" : "David",
"StudentAge" : 22,
"StudentFavouriteTechnicalSubject" : [
"Java"
]
}쿼리 동작 원리 살펴보기
결과를 보면 Mike와 David의 문서만 반환되고, Larry의 문서는 제외되었습니다. 그 이유를 단계별로 분석해 보겠습니다.
$nin: ['C++', 'Java']는 배열 내에서 'C++' 또는 'Java'에 해당하지 않는 요소를 찾습니다. Larry의 배열에는 'C'라는 값이 있어 이 조건에 걸리게 됩니다. 여기에 $elemMatch가 해당 조건을 만족하는 요소가 하나라도 있는지 검사하고, 최종적으로 $not이 이 조건을 반전시켜 '제공된 배열에 없는 값이 하나도 없는' 문서, 즉 모든 요소가 ['C++', 'Java'] 범위 안에 속하는 문서만 최종 결과로 남게 됩니다.
정리하면, Mike의 ['C++', 'Java']와 David의 ['Java']는 모두 제공된 배열의 부분 집합이므로 매칭에 성공하고, 'C'를 포함한 Larry의 배열은 제외되는 것입니다. 이 패턴은 배열 필드가 허용된 값 목록 안에서만 구성되었는지 검증할 때 유용하게 활용할 수 있습니다.