MongoDB에서 배열 필드 안에 중복된 값이 있는지 확인하려면 aggregate() 메서드를 활용하는 것이 가장 효과적입니다. 이 글에서는 실제 예제를 통해 배열의 중복 요소를 찾아내는 과정을 단계별로 살펴보겠습니다.
1. 샘플 데이터로 컬렉션 생성하기
먼저 테스트에 사용할 문서들을 포함한 컬렉션을 생성합니다. 두 번째 문서에는 의도적으로 중복된 과목명을 넣었습니다.
> db.demo756.insertOne({"SubjectName":["MySQL","MongoDB","Java"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5eb01e0d5637cd592b2a4add")
}
> db.demo756.insertOne({"SubjectName":["MongoDB","MySQL","MongoDB","C","C+","MySQL"]});
{
"acknowledged" : true,
"insertedId" : ObjectId("5eb01e2b5637cd592b2a4ade")
}2. find()로 전체 문서 조회하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.demo756.find();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5eb01e0d5637cd592b2a4add"), "SubjectName" : [ "MySQL", "MongoDB", "Java" ] }
{ "_id" : ObjectId("5eb01e2b5637cd592b2a4ade"), "SubjectName" : [ "MongoDB", "MySQL", "MongoDB", "C", "C+", "MySQL" ] }두 번째 문서의 SubjectName 배열에는 'MongoDB'와 'MySQL'이 각각 두 번씩 들어 있어 중복이 발생한 상태입니다.
3. 집계 파이프라인으로 배열 중복 확인하기
다음은 배열 내부의 중복 값을 검출하는 핵심 쿼리입니다.
> db.demo756.aggregate([
... {"$project": {"SubjectName":1}},
... {"$unwind":"$SubjectName"},
... {"$group": {"_id":{"_id":"$_id", "Name":"$SubjectName"}, "count":{"$sum":1}}},
... {"$match": {"count":{"$gt":1}}},
... {"$group": {"_id": "$_id._id", "SubjectName":{"$addToSet":"$_id.Name"}}}
... ])쿼리 실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5eb01e2b5637cd592b2a4ade"), "SubjectName" : [ "MongoDB", "MySQL" ] }집계 파이프라인 동작 원리
각 스테이지가 어떤 역할을 하는지 살펴보면 이해가 쉽습니다.
- $project: 분석에 필요한 SubjectName 필드만 남겨 불필요한 데이터를 제외합니다.
- $unwind: 배열을 개별 요소 단위의 문서로 분해합니다. 하나의 배열이 여러 개의 문서로 펼쳐집니다.
- $group: 문서 ID(_id)와 배열 값(Name)을 조합해 그룹화하고, $sum으로 각 값이 등장한 횟수를 계산합니다.
- $match: count가 1보다 큰 경우, 즉 두 번 이상 등장한 값(중복)만 필터링합니다.
- $addToSet: 마지막으로 원래 문서 ID 기준으로 재그룹화하여 중복된 값들의 목록을 배열로 반환합니다.
결과를 보면 중복이 없던 첫 번째 문서는 제외되고, 'MongoDB'와 'MySQL'이 중복된 두 번째 문서만 정확히 검출된 것을 확인할 수 있습니다. 이 패턴은 대용량 컬렉션에서도 데이터 품질 점검이나 정제 작업 시 유용하게 활용할 수 있습니다.