MongoDB에서 내부 배열의 특정 객체 값 합계로 정렬하기
내부 배열(inner array)에 포함된 특정 객체의 값을 집계한 뒤, 그 합계를 기준으로 문서를 정렬하려면 MongoDB의 애그리게이션 프레임워크를 활용해야 합니다. 이때 $unwind, $group, $sum, $cond, $sort 연산자를 조합하면 원하는 결과를 손쉽게 얻을 수 있습니다.
먼저 예제에 사용할 컬렉션을 생성하고 문서를 삽입해 보겠습니다.
> db.demo189.insertOne(
... {
... "_id" : 100,
... "List" : [
... {
... "Value" : 10
... },
... {
... "Value" : 20
... },
... {
... "Value" : 10
... }
... ]
... }
...);
{ "acknowledged" : true, "insertedId" : 100 }
> db.demo189.insertOne(
... {
... "_id" : 101,
... "List" : [
... {
... "Value" : 10
... },
... {
... "Value" : 10
... },
... {
... "Value" : 10
... }
... ]
... }
...);
{ "acknowledged" : true, "insertedId" : 101 }
find() 메서드를 사용하면 컬렉션의 모든 문서를 확인할 수 있습니다.
> db.demo189.find();
이 명령은 다음과 같은 출력을 생성합니다.
{ "_id" : 100, "List" : [ { "Value" : 10 }, { "Value" : 20 }, { "Value" : 10 } ] }
{ "_id" : 101, "List" : [ { "Value" : 10 }, { "Value" : 10 }, { "Value" : 10 } ] }특정 객체 값의 합계를 기준으로 정렬하는 쿼리
다음은 내부 배열에서 Value가 10인 요소의 개수를 집계한 후, 해당 합계가 큰 순서대로 문서를 정렬하는 쿼리입니다.
> db.demo189.aggregate([
... { "$unwind" : "$List" },
... { "$group" : {
... "_id" : "$_id",
... "total" : {
... "$sum" : {
... "$cond" : {
... "if" : { "$eq" : [ "$List.Value", 10 ] },
... "then" : 1,
... "else" : 0
... }
... }
... },
... "List" : {
... "$push" : {
... "Value" : "$List.Value"
... }
... }
... }},
... { "$sort" : { "total" : -1 } },
... { "$project" : {
... "List" : 1
... }}
...])
쿼리 동작 방식
이 애그리게이션 파이프라인은 다음 단계로 동작합니다.
- $unwind:
List배열의 각 요소를 개별 문서로 분해합니다. - $group:
_id를 기준으로 문서를 그룹화하면서, $cond와 $eq를 사용해Value가 10인 경우에만 1을 더하는 $sum 계산으로total필드를 만듭니다. - $push: 분해되었던
List배열을 원래 형태로 되돌립니다. - $sort:
total값을 기준으로 내림차순(-1) 정렬합니다. - $project: 최종 출력에서
List필드만 포함시킵니다.
쿼리 실행 결과는 다음과 같습니다.
{ "_id" : 101, "List" : [ { "Value" : 10 }, { "Value" : 10 }, { "Value" : 10 } ] }
{ "_id" : 100, "List" : [ { "Value" : 10 }, { "Value" : 20 }, { "Value" : 10 } ] }출력 결과를 살펴보면, _id가 101인 문서(Value가 10인 요소 3개)가 _id가 100인 문서(Value가 10인 요소 2개)보다 먼저 표시되는 것을 확인할 수 있습니다. 즉, 지정한 조건에 부합하는 값의 합계가 더 큰 문서부터 우선적으로 정렬됩니다.