개요
MongoDB에서 특정 배열과 유사한 요소를 가진 문서를 찾고, 일치하는 정도(유사도)에 따라 결과를 정렬해야 하는 경우가 종종 있습니다. 예를 들어, 사용자가 관심 있는 과목 목록과 비슷한 과목 배열을 가진 문서를 유사도가 높은 순으로 조회하고 싶다면 애그리게이션 파이프라인(Aggregation Pipeline)을 활용하면 됩니다.
이 글에서는 $unwind, $match, $group, $project, $sort 단계를 조합하여 유사한 배열을 가진 문서를 검색하고 유사도 백분율로 정렬하는 방법을 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성
먼저 문서를 포함하는 컬렉션을 생성합니다. 각 문서는 과목 목록을 담은 ListOfSubject 배열 필드를 가지고 있습니다.
> db.demo123.insertOne({"ListOfSubject":['MySQL', 'MongoDB', 'Java']});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2f24ac140daf4c2a3544b8")
}
> db.demo123.insertOne({"ListOfSubject":['Python', 'MongoDB', 'C']});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2f24cd140daf4c2a3544b9")
}
> db.demo123.insertOne({"ListOfSubject":['MySQL', 'MongoDB', 'C++']});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e2f24ce140daf4c2a3544ba")
}2. 저장된 문서 확인하기
find() 메서드를 사용하면 컬렉션의 모든 문서를 조회할 수 있습니다.
> db.demo123.find();
위 쿼리는 다음과 같은 결과를 출력합니다.
{ "_id" : ObjectId("5e2f24ac140daf4c2a3544b8"), "ListOfSubject" : [ "MySQL", "MongoDB", "Java" ] }
{ "_id" : ObjectId("5e2f24cd140daf4c2a3544b9"), "ListOfSubject" : [ "Python", "MongoDB", "C" ] }
{ "_id" : ObjectId("5e2f24ce140daf4c2a3544ba"), "ListOfSubject" : [ "MySQL", "MongoDB", "C++" ] }3. 유사한 배열을 가진 문서 검색 및 유사도 정렬 쿼리
이제 기준이 되는 배열과 유사한 문서를 찾아 유사도 순으로 정렬하는 애그리게이션 쿼리를 작성해 보겠습니다. 여기서는 ['MySQL', 'MongoDB', 'Java'] 배열을 기준으로 사용합니다.
> var subjects = ['MySQL', 'MongoDB', 'Java'];
> db.demo123.aggregate([
... {$unwind: "$ListOfSubject"},
... {$match: {ListOfSubject:{ $in:subjects}}},
... {$group: {_id: "$_id", number: {$sum: 1}}},
... {$project: {_id: 1, number: 1, percentage: {$divide:["$number",subjects.length]}}},
... {$sort: {percentage: -1}}
... ]);쿼리 동작 원리
- $unwind: 각 문서의
ListOfSubject배열을 개별 요소로 분해합니다. - $match: 기준 배열(
subjects)에 포함된 과목만 필터링합니다. - $group: 문서 ID별로 일치한 요소의 개수를 합산합니다.
- $project: 일치 개수를 기준 배열의 전체 길이로 나누어 유사도 백분율을 계산합니다.
- $sort: 유사도 내림차순으로 결과를 정렬합니다.
4. 실행 결과
위 쿼리는 다음과 같은 출력을 생성합니다.
{ "_id" : ObjectId("5e2f24ac140daf4c2a3544b8"), "number" : 3, "percentage" : 1 }
{ "_id" : ObjectId("5e2f24ce140daf4c2a3544ba"), "number" : 2, "percentage" : 0.6666666666666666 }
{ "_id" : ObjectId("5e2f24cd140daf4c2a3544b9"), "number" : 1, "percentage" : 0.3333333333333333 }결과 해석
결과를 보면 첫 번째 문서는 기준 배열 ['MySQL', 'MongoDB', 'Java']와 세 개의 요소가 모두 일치하여 유사도가 1(100%)입니다. 두 번째 문서는 두 개의 요소(MySQL, MongoDB)가 일치하여 약 66.7%, 세 번째 문서는 한 개의 요소(MongoDB)만 일치하여 약 33.3%의 유사도를 보입니다. 이처럼 애그리게이션 파이프라인을 활용하면 배열 간 유사도를 손쉽게 계산하고, 그 값을 기준으로 문서를 정렬할 수 있습니다.