ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MongoDB] 조건을 주어 find하자! Aggregate
    Programing/DataBase 2016. 9. 6. 15:36

    MongoDB Aggregate


    어떠한 데이터 베이스를 사용을 하더라도 Select, Find 등 디비값을 검색하는 것은 필수다.

    당연히 데이터를 집어 넣었기 때문에 찾아야 된다.


    일반적으로 전체를 검색하는 쿼리문 정도는 모두 알고 있다.


    대표적인 RDBMS 검색 쿼리문 

    Select * from TABLE


    MongoDB의 검색 쿼리문

    db.COLLECTION.find({});


    하지만 언제나 전체를 검색할 수는 없다.


    원하는 값만 추출하거나 검색된 데이터를 통해 계산을 한다던가 등등 많은 일이 생긴다.

    RDBMS의 group by문은 대부분 많이 알고, 쓰고 있을 것이다.


    그렇다면 MongoDB에서 조건을 주며, 검색을 하려면 어떻게 할까?

    find를 이용하여 어느정도 조건을 주며 검색은 가능하다.


    예를 들어 test라는 콜렉션이 다음과 같은 제약을 가졌다고 가정했을때,


    test Collection

    {_id:number, name:String, desc:Number, price:Number}

    숫자형인 _id 필드        ->> 고유 값이므로 겹치지 않는다.(1,2,3,4....로 증가)

    문자열형인 name 필드  ->> 이름 문자열 값 겹칠 수 있다.

    숫자형인 desc 필드      ->> 구분 숫자 값 겹칠 수 있다.

    숫자형인 price 필드      ->> 가격 숫자 값 겹칠 수 있다.

    라고 콜렉션을 하나 만들었다 치자!


    1
    db.test.find({desc:3});
    cs

    --> desc가 3인 것들을 죄다 찾는다.


    1
    db.test.find({desc:{$gt:0,$lt:10}});
    cs

    --> desc가 0보다 크고 10보다 작은 데이터를 찾는다.


    1
    db.test.find({desc:{$gt:0,$lt:10}},{sort:{_id:-1},limit:10});
    cs

    --> desc가 0보다 크고 10보다 작은 데이터를 _id값 오름차 순으로 10개 보여준다.


    이처럼 간단한 조건을 주어서 검색하는 것은 어렵지 않게 가능하다.


    그러면 

    첫째로! desc 별로 price값들의 평균을 알려면?

    db.test.find({});로 값들을 찾은 이후 검색된 값을 이용 하여..

    각 desc 값들의 갯수를 판단하고 각 desc별 price를 더한 이 후 desc갯수로 나눌 것인가?


    둘째로! desc별 데이터 중 price가 1000이 넘는 김씨들의 갯수를 찾으려면?

    db.test.find({});으로 검색 하고

    결과 값 desc별로 price가 1000이 넘는 것을 추출하고

    그중 name이 김씨를 찾으면 되나?


    오! 그러면 되네!

    신난다!!!


    하나도 안신난다...

    만약 검색된 데이터들이 무지막지하게 많으면 평균하나 구할때 가슴이 아프지 않을까..




    하지만 aggregate를 이용하면 간단하게 가능하다.


    일단 첫번째문제는

    1
    db.test.aggregate($group:{_id:'$desc',avg:{$avg:'$price'}}});
    cs

    이거 한줄이면 끝난다. _id값을 desc별로 묶어서 price의 평균 값을 avg라는 필드로 띄워준다.


    두번째 문제는

    1
    2
    3
    4
    db.test.aggregate([
                    {$match:{name:{$regex:/^김/},price:{$gt:1000}},
                    {$group:{_id:{'$desc'},count:{$sum:1}}
                    ]);
    cs

    이렇게 된다.


    설명을 하자면

    일단 test라는 콜렉션에서 name필드 중 김씨면서 price가 1000 이상인 값들을 먼저 매칭한다.

    그 이후 그 match된 김씨들을 desc별로 묶어서 카운트를 샌다.


    aggregate의 함수로 보이는 match,group이 보이는데 예제에는 안적었지만 project라는 묶음 개념도 있다.

    더 자세한 내용은 몽고디비 공식 docs를 확인하자!

    (mongodb 공식 홈페이지의 간단한 aggregate의 예제 그림)


    물론 조건이 많아지고 많아지고 많아질 수록 너무나도 긴 json형식의 구문이 될 것이다.

    그래도 find로 collection 자체의 모든 값을 검색된 결과를 이용하여,

    함수하나 작성하여 검색을 해야하는 노고는 충분히 줄일 수 있다.



    ps1. 코드가 틀릴 수도 있습니다.. 너무 급하게 작성한 포스팅이기에..

    ps2. find와 aggregate의 $match는 상당히 흡사한데 간단한 조건일 때 어떠한 것이 효율이 좋을까요?



    댓글

Designed by Tistory.