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

MongoDB에서 필드의 중복(비고유) 값을 모두 찾는 방법

MongoDB에서 특정 필드에 중복되어 저장된 값, 즉 비고유(non-distinct) 값을 모두 찾고 싶다면 aggregate() 메서드를 활용하면 됩니다. 이 글에서는 예제 컬렉션을 만들고, $group$match 연산자를 조합하여 중복된 값을 손쉽게 조회하는 방법을 단계별로 살펴보겠습니다.

1. 예제 컬렉션 생성하기

먼저 테스트에 사용할 컬렉션을 만들고 문서를 삽입합니다. 아래 예제에서는 사용자 이름(UserName)과 나이(UserAge)를 담은 문서들을 insertOne() 메서드로 추가합니다.

> db.findAllNonDistinctDemo.insertOne({"UserName":"John","UserAge":28});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c995078863d6ffd454bb647")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"Larry","UserAge":21});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c995081863d6ffd454bb648")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"Larry","UserAge":23});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c995089863d6ffd454bb649")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"David","UserAge":22});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c995093863d6ffd454bb64a")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"John","UserAge":26});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c99509d863d6ffd454bb64b")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"Robert","UserAge":24});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c9950a7863d6ffd454bb64c")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"Robert","UserAge":25});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c9950b1863d6ffd454bb64d")
}
> db.findAllNonDistinctDemo.insertOne({"UserName":"Mike","UserAge":29});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5c9950bc863d6ffd454bb64e")
}

2. find()로 전체 문서 확인하기

컬렉션에 저장된 모든 문서를 확인하려면 find() 메서드를 사용합니다. pretty()를 붙이면 결과가 보기 좋게 정렬되어 출력됩니다.

> db.findAllNonDistinctDemo.find().pretty();

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

{
    "_id" : ObjectId("5c995078863d6ffd454bb647"),
    "UserName" : "John",
    "UserAge" : 28
}
{
    "_id" : ObjectId("5c995081863d6ffd454bb648"),
    "UserName" : "Larry",
    "UserAge" : 21
}
{
    "_id" : ObjectId("5c995089863d6ffd454bb649"),
    "UserName" : "Larry",
    "UserAge" : 23
}
{
    "_id" : ObjectId("5c995093863d6ffd454bb64a"),
    "UserName" : "David",
    "UserAge" : 22
}
{
    "_id" : ObjectId("5c99509d863d6ffd454bb64b"),
    "UserName" : "John",
    "UserAge" : 26
}
{
    "_id" : ObjectId("5c9950a7863d6ffd454bb64c"),
    "UserName" : "Robert",
    "UserAge" : 24
}
{
    "_id" : ObjectId("5c9950b1863d6ffd454bb64d"),
    "UserName" : "Robert",
    "UserAge" : 25
}
{
    "_id" : ObjectId("5c9950bc863d6ffd454bb64e"),
    "UserName" : "Mike",
    "UserAge" : 29
}

출력 결과를 보면 Larry, John, Robert라는 이름이 각각 두 번씩 등장하는 것을 확인할 수 있습니다. 이제 이 중복 값들을 쿼리로 찾아보겠습니다.

3. aggregate()로 중복(비고유) 값 찾기

필드의 비고유 값을 찾으려면 애그리게이션 파이프라인에서 두 단계를 거칩니다.

  • $group: UserName 필드를 기준으로 그룹화하고, $sum: 1을 사용해 각 이름이 등장한 횟수를 카운트합니다.
  • $match: 카운트가 1보다 큰(즉, 두 번 이상 등장한) 값만 필터링합니다.
> db.findAllNonDistinctDemo.aggregate([
...     { "$group": {
...         "_id": "$UserName",
...         "Counter": { "$sum": 1 }
...     }},
...     { "$match": {
...         "Counter": { "$gt": 1 }
...     }}
... ]).pretty();

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

{ "_id" : "Robert", "Counter" : 2 }
{ "_id" : "Larry", "Counter" : 2 }
{ "_id" : "John", "Counter" : 2 }

결과 해석

실행 결과를 보면 Robert, Larry, John 세 개의 이름이 각각 2번씩 중복되어 나타났음을 알 수 있습니다. 반면 David와 Mike는 한 번만 등장했기 때문에 결과에서 제외됩니다.

이처럼 $group으로 값별 개수를 집계한 뒤 $match로 개수가 2 이상인 항목만 걸러내면, MongoDB에서도 SQL의 GROUP BY ... HAVING COUNT(*) > 1과 동일한 효과를 얻을 수 있습니다. 대용량 컬렉션에서 중복 데이터를 분석하거나 데이터 정합성을 점검할 때 매우 유용한 패턴이므로 꼭 기억해 두시기 바랍니다.