반응형

일단 엘라스틱서치로 mysql 정도의 group by는기대하지 말자.

 

우선 기본적인 group by인 "aggs"를 쓰기 위해서는 인덱스를 처음 만들때 등록하는 매핑에서 옵션을 추가해 주어야 한다.

 

numeric인 경우는 상관없는데 text인 경우에는 추가적인 옵션을 주어야한다.

 

{ "mappings": { "properties": { "site_reg_date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "ip": { "type": "text","fielddata": true }, "subject": { "type": "text" } } } }

 

이렇게 컬럼에 "fielddata": true 를 추가해준다. 이 부분을 빼고 만들면 aggs가 작동하지 않는다.

 

그런데 text로는 aggs를 하기가 힘들다. 가급적이면 numeric이나 date, keyword로 만든 컬럼만 사용하도록 하자.

 

{ "mappings": { "properties": { "site_reg_date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }, "ip": { "type": "keyword"}, "subject": { "type": "keyword" } } } }

 

기본적인 aggs 쿼리를 보자.

 

{
  "size": 0,
  "aggs": {
    "referer": {
      "terms": {
        "field": "ip"
      }
    }
  }
}

 

이렇게 하면

 

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 32,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "referer" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "109.*.*.2",
          "doc_count" : 11
        },
        {
          "key" : "23.*.*.61",
          "doc_count" : 11
        },
        {
          "key" : "106.*.*.71",
          "doc_count" : 5
        },
        {
          "key" : "183.*.*.48",
          "doc_count" : 2
        },
        {
          "key" : "52.*.*.126",
          "doc_count" : 1
        },
        {
          "key" : "74.*.*.36",
          "doc_count" : 1
        },
        {
          "key" : "74.*.*.37",
          "doc_count" : 1
        }
      ]
    }
  }
}

 

이렇게 나온다. 여기서 다시 count가 2 이상인 값들만 보고 싶다면...

 

{
  "size": 0,
  "aggs": {
    "countfield": {
      "terms": {
        "field": "ip",
        "min_doc_count": 2
      }
    }
  }
}

 

이렇게 해준다. 그러면

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 32,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "countfield" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "109.*.*.2",
          "doc_count" : 11
        },
        {
          "key" : "23.*.*.61",
          "doc_count" : 11
        },
        {
          "key" : "106.*.*.71",
          "doc_count" : 5
        },
        {
          "key" : "183.*.*.48",
          "doc_count" : 2
        }
      ]
    }
  }
}

 

이렇게 나온다. 

 

또하나 나오는 값을 limi를 주고 싶다면

 

{
  "size": 0,
  "aggs": {
    "result": {
      "terms": {
        "field": "ip",
        "size": 5
      }
    }
  }
}

 

이렇게 해주면 된다.

 

정렬도 된다.

 

{
  "size": 0,
  "aggs": {
    "result": {
      "terms": {
        "field": "ip",
        "min_doc_count": 2,
        "size": 5,
        "order": { "_key": "asc"}
      }
    }
  }
}

 

이렇게 하거나..

 

{
  "size": 0,
  "aggs": {
    "result": {
      "terms": {
        "field": "ip",
        "min_doc_count": 2,
        "size": 5,
        "order": { "_count": "asc"}
      }
    }
  }
}

 

이렇게 할 수 있다.

반응형

+ Recent posts