애그리게이션 프레임워크로 중복 문서 찾기
MongoDB에서 애그리게이션(aggregate) 프레임워크를 활용하면 특정 키 필드를 기준으로 컬렉션에 존재하는 모든 중복 문서를 효율적으로 찾아낼 수 있습니다. 이 글에서는 실제 예제를 통해 중복 데이터를 조회하는 전체 과정을 단계별로 살펴보겠습니다.
1단계: 예제용 컬렉션 생성
먼저 개념을 이해하기 위해 문서가 포함된 컬렉션을 생성하겠습니다. 아래 쿼리를 실행하면 컬렉션이 만들어지고 문서들이 차례로 삽입됩니다.
> db.findDuplicateByKeyDemo.insertOne({"StudentId":1,"StudentName":"John"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b168d10a061296a3c3a")
}
> db.findDuplicateByKeyDemo.insertOne({"StudentId":2,"StudentName":"Carol"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b1f8d10a061296a3c3b")
}
> db.findDuplicateByKeyDemo.insertOne({"StudentId":3,"StudentName":"Carol"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b248d10a061296a3c3c")
}
> db.findDuplicateByKeyDemo.insertOne({"StudentId":4,"StudentName":"John"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b2d8d10a061296a3c3d")
}
> db.findDuplicateByKeyDemo.insertOne({"StudentId":5,"StudentName":"Sam"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b398d10a061296a3c3e")
}
> db.findDuplicateByKeyDemo.insertOne({"StudentId":6,"StudentName":"Carol"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c7f5b438d10a061296a3c3f")
}
2단계: 전체 문서 확인
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.findDuplicateByKeyDemo.find().pretty();
실행 결과는 다음과 같습니다. 총 6개의 문서가 저장되어 있으며, 이름을 보면 'John'과 'Carol'이 여러 번 등장하는 것을 알 수 있습니다.
{
"_id" : ObjectId("5c7f5b168d10a061296a3c3a"),
"StudentId" : 1,
"StudentName" : "John"
}
{
"_id" : ObjectId("5c7f5b1f8d10a061296a3c3b"),
"StudentId" : 2,
"StudentName" : "Carol"
}
{
"_id" : ObjectId("5c7f5b248d10a061296a3c3c"),
"StudentId" : 3,
"StudentName" : "Carol"
}
{
"_id" : ObjectId("5c7f5b2d8d10a061296a3c3d"),
"StudentId" : 4,
"StudentName" : "John"
}
{
"_id" : ObjectId("5c7f5b398d10a061296a3c3e"),
"StudentId" : 5,
"StudentName" : "Sam"
}
{
"_id" : ObjectId("5c7f5b438d10a061296a3c3f"),
"StudentId" : 6,
"StudentName" : "Carol"
}
3단계: 중복 문서 조회 쿼리 작성
다음은 $group, $match, $sort, $limit 스테이지를 조합하여 중복 문서를 찾는 애그리게이션 쿼리입니다.
> db.findDuplicateByKeyDemo.aggregate([
{ $group: {
_id: { StudentName: "$StudentName" },
UIDS: { $addToSet: "$_id" },
COUNTER: { $sum: 1 }
} },
{ $match: {
COUNTER: { $gte: 2 }
} },
{ $sort : { COUNTER : -1} },
{ $limit : 10 }
... ]).pretty();
쿼리 동작 원리
- $group: StudentName 필드 값을 기준으로 문서를 그룹화하고, 각 그룹에 속한 _id 값을 UIDS 배열에 모으며, COUNTER로 그룹 내 문서 개수를 집계합니다.
- $match: COUNTER 값이 2 이상($gte: 2)인 그룹, 즉 중복된 문서만 필터링합니다.
- $sort: 중복 횟수가 많은 순서대로 내림차순 정렬합니다.
- $limit: 결과를 상위 10개로 제한합니다.
실행 결과
아래 출력 결과를 보면 'Carol' 학생은 3번, 'John' 학생은 2번 등장하여 중복으로 판별되었고, 한 번만 나타난 'Sam'은 결과에서 제외된 것을 확인할 수 있습니다.
{
"_id" : {
"StudentName" : "Carol"
},
"UIDS" : [
ObjectId("5c7f5b248d10a061296a3c3c"),
ObjectId("5c7f5b438d10a061296a3c3f"),
ObjectId("5c7f5b1f8d10a061296a3c3b")
],
"COUNTER" : 3
}
{
"_id" : {
"StudentName" : "John"
},
"UIDS" : [
ObjectId("5c7f5b2d8d10a061296a3c3d"),
ObjectId("5c7f5b168d10a061296a3c3a")
],
"COUNTER" : 2
}
이처럼 애그리게이션 파이프라인을 활용하면 별도의 스크립트 없이도 MongoDB 셸에서 바로 중복 데이터를 손쉽게 식별할 수 있습니다. 필요에 따라 $limit 값을 조정하거나 $match 조건을 변경하여 원하는 형태로 결과를 가공할 수 있습니다.