여러 필드를 기준으로 데이터를 그룹화하고, 함께 묶인 중복 필드 값의 개수까지 확인하려면 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건으로 집계되는 것을 확인할 수 있습니다.