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

MongoDB에서 여러 필드로 그룹화해 함께 묶인 중복 필드 값 개수 구하기

여러 필드를 기준으로 데이터를 그룹화하고, 함께 묶인 중복 필드 값의 개수까지 확인하려면 MongoDB의 aggregate 집계 파이프라인과 $cond 연산자를 활용하면 됩니다. $cond는 불리언 표현식을 평가하여, 조건이 참일 때와 거짓일 때 지정된 두 반환 표현식 중 하나를 반환하는 연산자입니다.

이 방법은 Name1과 Name2처럼 두 필드에 저장된 값의 순서만 다른 경우(예: Chris-David과 David-Chris)에도 같은 그룹으로 묶어 개수를 집계할 때 특히 유용합니다.

1단계: 컬렉션 생성 및 문서 삽입

먼저 demo536 컬렉션을 만들고 문서를 차례로 삽입합니다.

> db.demo536.insertOne({"Name1":"Chris","Name2":"David"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e8c843eef4dcbee04fbbc01")
}
> db.demo536.insertOne({"Name1":"David","Name2":"Chris"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e8c843fef4dcbee04fbbc02")
}
> db.demo536.insertOne({"Name1":"Bob","Name2":"Sam"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e8c843fef4dcbee04fbbc03")
}
> db.demo536.insertOne({"Name1":"Chris","Name2":"David"});
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e8c843fef4dcbee04fbbc04")
}

2단계: find() 메서드로 전체 문서 확인

find() 메서드를 사용해 컬렉션에 저장된 모든 문서를 조회합니다.

> db.demo536.find();

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

{ "_id" : ObjectId("5e8c843eef4dcbee04fbbc01"), "Name1" : "Chris", "Name2" : "David" }
{ "_id" : ObjectId("5e8c843fef4dcbee04fbbc02"), "Name1" : "David", "Name2" : "Chris" }
{ "_id" : ObjectId("5e8c843fef4dcbee04fbbc03"), "Name1" : "Bob", "Name2" : "Sam" }
{ "_id" : ObjectId("5e8c843fef4dcbee04fbbc04"), "Name1" : "Chris", "Name2" : "David" }

3단계: 여러 필드로 그룹화하는 집계 쿼리 실행

다음은 $project 단계에서 $cond로 두 이름의 순서를 정규화한 뒤, $group으로 그룹화하고 $sum으로 개수를 집계하는 쿼리입니다.

> db.demo536.aggregate([
... {
...    $project:
...    {
...       FirstName1:
...       {
...          $cond: { if: { $gte: [ "$Name1", "$Name2" ] }, then: "$Name2", else: "$Name1" }
...       },
...       FirstName2:
...       {
...          $cond: { if: { $lt: [ "$Name1", "$Name2" ] }, then: "$Name2", else: "$Name1" }
...       }
...    }
... }
... ,{
...    $group:
...    {
...       _id:
...       {
...          Name1: "$FirstName1",
...          Name2: "$FirstName2"
...       }
...       ,count: { $sum: 1}
...    }
... }
... ])

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

{ "_id" : { "Name1" : "Bob", "Name2" : "Sam" }, "count" : 1 }
{ "_id" : { "Name1" : "Chris", "Name2" : "David" }, "count" : 3 }

쿼리 동작 원리

  • $project + $cond: $gte(크거나 같음)와 $lt(작음) 비교 연산자를 사용해 Name1과 Name2 중 사전순으로 앞선 값을 FirstName1에, 뒤따르는 값을 FirstName2에 배치합니다. 덕분에 Chris-David과 David-Chris처럼 순서만 다른 문서도 동일한 형태로 정규화됩니다.
  • $group: _id를 Name1과 Name2로 구성된 복합 키로 지정하여 여러 필드를 한 번에 그룹화합니다.
  • count: { $sum: 1 }: 각 그룹에 속한 문서 수를 합산해 해당 조합이 몇 번 등장했는지, 즉 중복 횟수를 계산합니다.

결과를 보면 Bob-Sam 조합은 1건뿐이지만, Chris-David 조합은 Chris/David으로 저장된 2건과 David/Chris으로 저장된 1건이 모두 같은 그룹으로 묶여 총 3건으로 집계되는 것을 확인할 수 있습니다.