Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB 집계($facet)로 여러 필드 기준 문서 개수 세는 방법

MongoDB 집계로 여러 필드 기준 개수 세기

여러 필드를 기준으로 문서 수를 집계하려면 MongoDB의 $facet 연산자를 활용하면 됩니다. $facet은 단일 단계(single stage) 안에서 동일한 입력 문서 집합에 대해 여러 개의 집계 파이프라인을 동시에 처리할 수 있게 해주는 강력한 기능입니다.

먼저 예제에 사용할 컬렉션을 생성하고 문서를 삽입해 보겠습니다.

> db.demo721.insertOne(
...     {
...         "details1": {
...             "id":101
...         },
...         "details2": {
...             "id":101
...         },
...         "details3": {
...             "id":101
...         }
...     }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5eaaebdd43417811278f5887")
}
>
>
> db.demo721.insertOne(
...     {
...         "details1": {
...             "id":101
...         },
...         "details2": {
...             "id":102
...         },
...         "details3": {
...             "id":102
...         }
...     }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5eaaebe943417811278f5888")
}

find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.

> db.demo721.find();

위 명령을 실행하면 다음과 같은 결과가 출력됩니다.

{ "_id" : ObjectId("5eaaebdd43417811278f5887"), "details1" : { "id" : 101 }, "details2" : { "id" : 101 }, "details3" : { "id" : 101 } }
{ "_id" : ObjectId("5eaaebe943417811278f5888"), "details1" : { "id" : 101 }, "details2" : { "id" : 102 }, "details3" : { "id" : 102 } }

여러 필드 기준 카운트 쿼리 작성하기

다음은 여러 필드를 기준으로 개수를 집계하는 쿼리입니다. 이 쿼리는 크게 두 단계로 동작합니다. 먼저 $facet 내부에서 두 개의 하위 파이프라인을 실행하는데, 하나는 $addToSet과 $setUnion을 이용해 모든 details 필드에 등장하는 고유 id 값을 수집하고, 다른 하나는 각 문서에서 details1.id, details2.id, details3.id 값만 추출합니다. 이후 $unwind로 배열을 풀어낸 뒤, $group과 $cond 조건식을 조합하여 각 id가 각 필드별로 몇 번 등장했는지 합산합니다.

> db.demo721.aggregate([
...     {$facet:{
...         ids:[
...             {$group:{ _id:null,
...                d3:{$addToSet: "$details3.id"},
...                d2:{$addToSet:"$details2.id"},
...                d1:{$addToSet:"$details1.id"}}},
...             {$project:{ _id:0,
...                listofall:{$setUnion:["$d1","$d2","$d3"]}}}],
...         d:[{$project:{ _id:0,
...             a1:"$details1.id",
...             a2:"$details2.id",
...             a3:"$details3.id"}}]}},
... {$unwind:"$d"},
... {$unwind:"$ids"},
... {$unwind:"$ids.listofall"},
... {$group:{ _id:"$ids.listofall",
...     details1id:{$sum:{$cond:[{$eq:["$d.a1","$ids.listofall"]},1,0]}},
...     details2id:{$sum:{$cond:[{$eq:["$d.a2","$ids.listofall"]},1,0]}},
...     details3id:{$sum:{$cond:[{$eq:["$d.a3","$ids.listofall"]},1,0]}}}}])

쿼리를 실행하면 다음과 같은 결과가 출력됩니다.

{ "_id" : 102, "details1id" : 0, "details2id" : 1, "details3id" : 1 }
{ "_id" : 101, "details1id" : 2, "details2id" : 1, "details3id" : 1 }

결과 해석

출력 결과를 보면 id 101은 details1 필드에서 2번, details2와 details3 필드에서 각각 1번씩 등장했습니다. 반면 id 102는 details1에는 전혀 없었고(0), details2와 details3에서 각각 1번씩 나타났습니다. 이처럼 $facet을 활용하면 여러 필드에 흩어진 값을 한 번의 집계 파이프라인으로 손쉽게 비교·카운트할 수 있습니다.