배열에 포함된 각 요소의 등장 횟수(빈도)를 세고 싶다면 MongoDB의 aggregate() 메서드와 $sum 연산자를 함께 사용하면 됩니다. 이 글에서는 실제 예제를 통해 단계별로 살펴보겠습니다.
1. 샘플 데이터 준비하기
먼저 문서가 포함된 컬렉션을 생성합니다. 각 문서에는 이름들이 담긴 배열 필드가 들어 있습니다.
> db.demo184.insertOne({"Names":["Chris","David","Bob"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e3999fb9e4f06af55199805")
}
> db.demo184.insertOne({"Names":["Chris","Mike"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399a0d9e4f06af55199806")
}
> db.demo184.insertOne({"Names":["Chris","Bob","Carol"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399a209e4f06af55199807")
}2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo184.find();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e3999fb9e4f06af55199805"), "Names" : [ "Chris", "David", "Bob" ] }
{ "_id" : ObjectId("5e399a0d9e4f06af55199806"), "Names" : [ "Chris", "Mike" ] }
{ "_id" : ObjectId("5e399a209e4f06af55199807"), "Names" : [ "Chris", "Bob", "Carol" ] }3. 집계 파이프라인으로 요소 빈도 계산하기
다음은 배열의 모든 요소에 대한 빈도를 한 번에 계산하는 쿼리입니다.
> db.demo184.aggregate([
... { "$unwind" : "$Names" },
... { "$group": { "_id": "$Names", "count": { "$sum": 1} } },
... { "$group": {
... "_id": null,
... "counts": {
... "$push": {
... "k": "$_id",
... "v": "$count"
... }
... }
... } },
... { "$replaceRoot": {
... "newRoot": { "$arrayToObject": "$counts" }
... } }
...])실행 결과는 다음과 같습니다.
{ "Carol" : 1, "David" : 1, "Chris" : 3, "Bob" : 2, "Mike" : 1 }쿼리 동작 원리
이 집계 파이프라인은 네 단계로 구성되어 있습니다.
$unwind: 각 문서의 Names 배열을 개별 요소 단위로 분해합니다. 예를 들어 ["Chris", "Mike"] 하나의 문서가 "Chris"와 "Mike" 두 개의 문서로 나뉩니다.
$group + $sum: 분해된 요소들을 이름 기준으로 그룹화하고, $sum: 1을 통해 각 이름이 등장한 횟수를 카운트합니다.
$group + $push: 앞서 만든 이름-카운트 쌍을 k(키)와 v(값) 형태의 배열로 묶습니다.
$replaceRoot + $arrayToObject: k/v 배열을 하나의 객체로 변환하여 최종적으로 각 이름이 키가 되고 빈도가 값이 되는 깔끔한 결과를 만들어 냅니다.
결과를 보면 "Chris"는 3번, "Bob"은 2번, 나머지 이름들은 각각 1번씩 등장했음을 한눈에 확인할 수 있습니다. 이 패턴은 태그 목록, 주문 항목, 로그 데이터 등 배열 필드의 통계를 낼 때 폭넓게 활용할 수 있습니다.