데이터베이스 NoSQL 심화 (mongoDB) - aggregation 주요 명령 (group/match/sort/sum)

4. aggregation 주요 명령 (group/match/sort/sum)

$group (GROUP BY), $match (WHERE), $sort (ORDER BY), $sum (SUM)

4.1. group & sum

  • SQL 구문과 비교하며 작성할 것
  • 한번에 만들기 어려우면, 일단 SQL 구문으로 만든 후, 유사 변경 예를 보며 mongodb aggregate로 바꿀 것
$group 기본 문법: { $group: { _id: , : { : }, ... }
  • _id 필드는 mandatory, 하지만, 전체 doc에 대한 계산값이 필요할 때는 null 로 넣으면 됨
# SQL: SELECT COUNT(*) AS count FROM zip
# mongodb aggreate:
result = db.zip.aggregate([
    {'$group' : 
        {
            '_id' : 'null', 
            'count' : {'$sum' : 1}
        }
    } 
])
for record in result:
    print(record)
{'_id': 'null', 'count': 29353}
# SQL: SELECT SUM(pop) AS count FROM zip
# mongodb aggreate:
result = db.zip.aggregate([
    {'$group' : 
        {
            '_id' : 'null', 
            'total' : {'$sum' : '$pop'}
        }
    } 
])
for record in result:
    print(record)
{'_id': 'null', 'total': 248408400}
# SQL: SELECT state, SUM(pop) FROM zip GROUP BY state
# mongodb aggreate:
result = db.zip.aggregate([
    {'$group' : 
        {
            '_id' : '$state', 
            'total_pop' : {'$sum' : '$pop'}
        }
    } 
])
for record in result:
    print(record)
{'_id': 'CA', 'total_pop': 29754890}
{'_id': 'MT', 'total_pop': 798948}
{'_id': 'MS', 'total_pop': 2573216}
{'_id': 'FL', 'total_pop': 12686644}
{'_id': 'AR', 'total_pop': 2350725}
{'_id': 'GA', 'total_pop': 6478216}
{'_id': 'WA', 'total_pop': 4866692}
{'_id': 'SC', 'total_pop': 3486703}
{'_id': 'MN', 'total_pop': 4372982}
{'_id': 'NE', 'total_pop': 1578139}
{'_id': 'MD', 'total_pop': 4781379}
{'_id': 'TN', 'total_pop': 4876457}
{'_id': 'DE', 'total_pop': 666168}
{'_id': 'DC', 'total_pop': 606900}
{'_id': 'AZ', 'total_pop': 3665228}
{'_id': 'ME', 'total_pop': 1226648}
{'_id': 'OR', 'total_pop': 2842321}
{'_id': 'AL', 'total_pop': 4040587}
{'_id': 'PA', 'total_pop': 11881643}
{'_id': 'RI', 'total_pop': 1003218}
{'_id': 'MA', 'total_pop': 6016425}
{'_id': 'NJ', 'total_pop': 7730188}
{'_id': 'NY', 'total_pop': 17990402}
{'_id': 'ND', 'total_pop': 638272}
{'_id': 'VT', 'total_pop': 562758}
{'_id': 'NM', 'total_pop': 1515069}
{'_id': 'CT', 'total_pop': 3287116}
{'_id': 'KY', 'total_pop': 3675484}
{'_id': 'OH', 'total_pop': 10846517}
{'_id': 'WY', 'total_pop': 453528}
{'_id': 'UT', 'total_pop': 1722850}
{'_id': 'HI', 'total_pop': 1108229}
{'_id': 'MI', 'total_pop': 9295297}
{'_id': 'AK', 'total_pop': 544698}
{'_id': 'WV', 'total_pop': 1793146}
{'_id': 'IA', 'total_pop': 2776420}
{'_id': 'WI', 'total_pop': 4891769}
{'_id': 'VA', 'total_pop': 6181479}
{'_id': 'IN', 'total_pop': 5544136}
{'_id': 'SD', 'total_pop': 695397}
{'_id': 'IL', 'total_pop': 11427576}
{'_id': 'MO', 'total_pop': 5110648}
{'_id': 'KS', 'total_pop': 2475285}
{'_id': 'LA', 'total_pop': 4217595}
{'_id': 'NH', 'total_pop': 1109252}
{'_id': 'OK', 'total_pop': 3145585}
{'_id': 'NC', 'total_pop': 6628637}
{'_id': 'TX', 'total_pop': 16984601}
{'_id': 'CO', 'total_pop': 3293755}
{'_id': 'ID', 'total_pop': 1006749}
{'_id': 'NV', 'total_pop': 1201833}
이해하고 실습하기
city 로 그룹핑해서, pop 의 합계를 출력하는데, 5개만 출력해보자
result = db.zip.aggregate([
    {'$group' : 
        {
            '_id' : '$city', 
            'total_pop' : {'$sum' : '$pop'}
        }
    },
    { '$limit' : 5 }
])
for record in result:
    print(record)
{'_id': 'WRANGELL', 'total_pop': 2573}
{'_id': 'METLAKATLA', 'total_pop': 1469}
{'_id': 'HYDER', 'total_pop': 116}
{'_id': 'HYDABURG', 'total_pop': 891}
{'_id': 'THORNE BAY', 'total_pop': 744}

4.2. sort

$sort 기본 문법: { $sort: { : , : ... } }
  • sort order는 1 또는 -1
# SQL: SELECT state, SUM(pop) FROM zip GROUP BY state ORDER BY SUM(pop)
# mongodb aggreate:
result = db.zip.aggregate([
    {'$group' : 
        {
            '_id' : '$state', 
            'total_pop' : {'$sum' : '$pop'}
        }
    }, 
    {'$sort' : 
        {'total_pop': 1} 
    },
    {'$limit' : 5},
    {'$project' : { '_id' : 0 }}
])
for record in result:
    print(record)
{'total_pop': 453528}
{'total_pop': 544698}
{'total_pop': 562758}
{'total_pop': 606900}
{'total_pop': 638272}

4.3. match

$match 기본 문법: { $match: { } }
# SQL: SELECT * FROM zip WHERE pop >= 100000 
# mongodb aggregate:
result = db.zip.aggregate([
    {'$match' : {'pop' : {'$gte' : 100000} } },
    {'$limit' : 5 }
])
for record in result:
    print(record)
{'_id': '10021', 'city': 'NEW YORK', 'loc': [-73.958805, 40.768476], 'pop': 106564, 'state': 'NY'}
{'_id': '10025', 'city': 'NEW YORK', 'loc': [-73.968312, 40.797466], 'pop': 100027, 'state': 'NY'}
{'_id': '11226', 'city': 'BROOKLYN', 'loc': [-73.956985, 40.646694], 'pop': 111396, 'state': 'NY'}
{'_id': '60623', 'city': 'CHICAGO', 'loc': [-87.7157, 41.849015], 'pop': 112047, 'state': 'IL'}
# SQL: SELECT * FROM zip WHERE state = 'MA' 
# mongodb aggregate:
result = db.zip.aggregate([
    {'$match' : {'state' : 'MA'}}
])
for record in result:
    print(record)
# SQL: SELECT COUNT(*) FROM zip WHERE state = 'MA' 
# mongodb aggregate:
result = db.zip.aggregate([

    {'$match' : {'state' : 'MA'}},

    {'$group' : {'_id' : 'null', 'count' : {'$sum' : 1}}} 

])
for record in result:
    print(record)
{'_id': 'null', 'count': 474}
이해하고 실습하기
state 로 그룹핑, state 가 MA 인 pop 의 합계를 출력하기
result = db.zip.aggregate([

    { '$match' : { 'state' : 'MA'}},

    { '$group' : { '_id' : '$state', 
                   'count' : { '$sum' : '$pop'}}
    }
    

])
for record in result:
    print(record)
{'_id': 'MA', 'count': 6016425}