MongoDB 내부 배열의 특정 필드 중복 확인하기
MongoDB에서 문서 안에 중첩된 내부(inner) 배열의 특정 필드 값이 중복되는지 확인하려면 aggregate() 메서드를 활용하면 됩니다. 이 글에서는 실제 예제를 통해 단계별로 확인 방법을 살펴보겠습니다.
1. 예제 컬렉션 생성 및 데이터 삽입
먼저 insertOne() 메서드를 사용해 demo347 컬렉션에 문서를 삽입합니다.
> db.demo347.insertOne(
... {
... "details": {
... "details1": [
... {
... Name: "Chris",
... Age: 21
... }
...
... ]
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e5532eaf8647eb59e5620af")
}
> db.demo347.insertOne(
... {
... "details": {
... "details1": [
... {
... Name: "David",
... Age: 22
... }
...
... ]
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e55330af8647eb59e5620b0")
}
> db.demo347.insertOne(
... {
... "details": {
... "details1": [
... {
... Name: "Chris",
... Age: 21
... }
...
... ]
... }
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5e55331cf8647eb59e5620b1")
}위 예제에서는 세 개의 문서를 삽입했습니다. 첫 번째와 세 번째 문서는 동일한 이름("Chris")을 가지고 있어 중복 데이터가 존재하는 상황입니다.
2. 저장된 문서 조회하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.demo347.find();
위 명령을 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
{ "_id" : ObjectId("5e5532eaf8647eb59e5620af"), "details" : { "details1" : [ { "Name" : "Chris", "Age" : 21 } ] } }
{ "_id" : ObjectId("5e55330af8647eb59e5620b0"), "details" : { "details1" : [ { "Name" : "David", "Age" : 22 } ] } }
{ "_id" : ObjectId("5e55331cf8647eb59e5620b1"), "details" : { "details1" : [ { "Name" : "Chris", "Age" : 21 } ] } }3. 집계 파이프라인으로 중복 필드 확인하기
이제 내부 배열의 특정 필드(여기서는 Name)의 중복 여부를 확인하는 쿼리입니다.
> db.demo347.aggregate([
... {"$unwind": "$details"},
... {"$unwind": "$details.details1"},
... {"$group" : { "_id": "$details.details1.Name", "count": { "$sum": 1 } } },
... {"$match": { "_id" :{ "$ne" : null } , "count" : { "$gt": 1} } }
... ])각 단계가 수행하는 역할은 다음과 같습니다.
- $unwind: 중첩된 배열을 개별 문서로 분해하여 각 요소를 독립적으로 처리할 수 있게 합니다.
- $group:
Name필드 값을 기준으로 문서를 그룹화하고,$sum: 1을 통해 각 이름이 등장한 횟수를 계산합니다. - $match: 값이 null이 아닌 문서만 대상으로 하며,
count가 1보다 큰 경우, 즉 중복된 항목만 최종 결과로 필터링합니다.
쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : "Chris", "count" : 2 }결과 해석
출력 결과를 보면 "Chris"라는 이름이 2번 등장했음을 의미합니다. 즉, 내부 배열의 Name 필드에 중복된 값이 존재한다는 뜻입니다. 반면 "David"는 한 번만 나타났기 때문에 결과에 포함되지 않았습니다.
이처럼 $unwind, $group, $match 단계를 조합한 집계 파이프라인을 활용하면 중첩된 배열 구조 안에서도 손쉽게 중복 데이터를 찾아낼 수 있습니다.