본문 바로가기

개발/db

[mongodb] MongoDB university - week5 : aggregation framework

https://university.mongodb.com/courses/10gen/M101JS/2015_May/courseware


sql에서의 group by는 다음과 같다.

몽고에서

db.products.aggregate([

{$group:

{

_id: "$manufacturer",

num_products: {$sum: 1}  //1씩 더한다. 가격같은필드를 더할때는 1대신 "$필드이름"

}

}

])


pipeline ( collection->ㅁ($project)->ㅁ($match)->ㅁ($group)->ㅁ($sort)->result  )

위의 배열의 각 item이 pipeline의 단계(stage)이다

$project는 document를 reshape.. 특정 필드를 선택해서 top으로 끌어올려 document를 reshape하는것임.. document와 1:1로 수행된다

$match는 filter the step. 예를들어 제조사로 그룹지었고 그 중에 애플, 삼성으로 필터링. n:1 filtering. document 수를 줄여줌

$group n:1

$sort 1:1

$skip n:1

$limit n:1

$unwind -데이터 normalize. 1:n 예를들어 tags: ["red", "blue"] 이면 tags: red tags: blue로 풀어줌

$out 1:1



compound grouping

db.products.aggregate([

{$group:

{

_id: {"maker": "$manufacturer", "category": "$category"}

num_products: {$sum: 1}

}

}

])


$sum, $avg, $min, $max, $push, $addtoset, $first, $last


$unwind, $sort, $limit

db.posts.aggregate([

{$unwind: "$tags"},   //document안에 배열 여러개 있으면 $unwind 프로퍼티추가

{$group:

{

_id: "$tags" //위의 경우 _id: {tag: "$tags", comment: "$comments"} 하면됨

count: {$sum: 1}

}

},

{$sort: {"count": -1}},

{$limit: 10},

{$project:         //project는 document를 reshape 함

{

_id: 0,           //_id필드를 보여주지 않겠다.

tag: "$_id",     //tag:  {$toLower: "$_id"},

count: 1         //count 그대로 가져오려면

}

}

])

project 프로퍼티에 아래와 같이 할 수 있음..

{

details: {category: "$category", price: {"$multiply": ["$price", 10]}}

}



$addToSet  - $push와 비슷하다. push는 중복 데이터가 들어간다.

db.products.aggregate([

{$group:

{

_id: { maker: "$manufacturer"},

categories: {$addToSet: "$category"}

}

}

])


$max, $min         //각 manufacturer마다 젤 높은 가격 보여줌

db.products.aggregate([

{$group:

{

_id: { maker: "$manufacturer"},

maxprice: {$max: "$price"}    

}

}

])


double $group stages

db.grades.aggregate([

{$group:              //학생의 hw, exam등의 성적 평균을 내고

{

_id: { class_id: "$class_id", student_id: "$student_id"},

ave: {$avg: "$score"}    

}

},

{$group:

{                    //학급별로 묶어서 각학생의 평균점수를 평균냄

_id: "$_id.class_id",

ave: {$avg: "$ave"}    

}

}

])


$match    filter  n:1

db.zips.aggregate([

{$match: {state: "CA"}},

{$group: 어쩌구}

])


$first, $last   //각 그룹의 첫번째나 마지막 값 얻을 수 있음

db.fun.aggregate([

    {$match:{a:0}},

    {$sort:{c:-1}}, 

    {$group:{_id:"$a", c:{$first:"$c"}}}

])