본문 바로가기
공부

Elasticsearch) Bool 복합 쿼리 , Should, 정확값 쿼리, 범위 쿼리

by son_i 2023. 12. 8.
728x90

query_string 쿼리는 여러 조건을 조합하기 좋지만 옵션이 한정되어있음.

 Data Body 검색에서 여러 쿼리를 조합하기 위해서는 상위에 bool 쿼리를 사용하고 그 안에 다른 쿼리들을 넣어 사용 가능.

 

bool 쿼리는 다음의 4개 인자를 가지고 있고 그 인자 안에 다른 쿼리들을 배열로 넣는 형식으로 동작.

  • must : 쿼리가 참인 도큐먼트 검색
  • must_not : 쿼리가 거짓인 도큐먼트 검색
  • should : 검색 결과 중 이 쿼리에 해당하는 도큐먼트들의 점수를 높임
  • filter : 쿼리가 참인 도큐먼트를 검색하지만 스코어를 계산하지 않음. must보다 검색속도가 빠르고 캐싱 가능

Bool Query

사용방법

GET <인덱스명>/_search
{
  "query": {
    "bool": {
      "must": [
        { <쿼리> }, …
      ],
      "must_not": [
        { <쿼리> }, …
      ],
      "should": [
        { <쿼리> }, …
      ],
      "filter": [
        { <쿼리> }, …
      ]
    }
  }
}

 

단어 quick과 구문 "lazy dog"이 포함된 모든 문서 검색하는 쿼리

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "message": "quick"
          }
        },
        {
          "match_phrase": {
            "message": "lazy dog"
          }
        }
      ]
    }
  }
}

Should

검색 점수를 조정할 수 있음

아래 입력시 

GET my_index/_search
{
  "query": {
    "match": {
      "message": "fox"
    }
  }
}

 

결과

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.32951736,
    "hits": [
      {
        "_index": "my_index",
        "_id": "1",
        "_score": 0.32951736,
        "_source": {
          "message": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_id": "4",
        "_score": 0.32951736,
        "_source": {
          "message": "Brown fox brown dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "2",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the lazy dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "3",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the quick dog"
        }
      }
    ]
  }
}

 

should를 사용해 laze라는 단어가 들어간 도큐먼트 점수 높이기

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "message": "fox"
          }
        }
      ],
      "should": [
        {
          "match": {
            "message": "lazy"
          }
        }
      ]
    }
  }
}

 

그리고 나서 결과 laze가 포함된 도큐먼트의 점수가 높아져 먼저 나오게 됐다. 

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.94896436,
    "hits": [
      {
        "_index": "my_index",
        "_id": "2",
        "_score": 0.94896436,
        "_source": {
          "message": "The quick brown fox jumps over the lazy dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "1",
        "_score": 0.32951736,
        "_source": {
          "message": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_id": "4",
        "_score": 0.32951736,
        "_source": {
          "message": "Brown fox brown dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "3",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the quick dog"
        }
      }
    ]
  }
}

정확값 쿼리 - Exact Value Query

지금까지 했던 full text 검색은 점수 기반 으로 정확도(relevancy)가 높은 결과부터 가져옴.

ES는 정확도를 고려하는 Full text외에도 검색 조건의 참/거짓만 판별해서 결과를 가져오는 것이 가능.

풀텍스트의 개념과 대비되어 이 특성을 정확값(Exact Value)라고 하는데 값이 정확히 일치하는지의 여부만을 따지는 검색.

 

Exact Value에는 term, range와 같은 쿼리들이 이 부분에 속하고 스코어를 계산하지 않기 때문에 보통 bool쿼리의 filter 내부에서 사용.

 

bool : filter

bool쿼리의 filter안에 하위 쿼리를 사용하면 스코어에 영향을 주지 않음.

 

1. fox로만 검색했을 때

GET my_index/_search
{
  "query": {
    "match": {
      "message": "fox"
    }
  }
}

 

결과

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 0.32951736,
    "hits": [
      {
        "_index": "my_index",
        "_id": "1",
        "_score": 0.32951736,
        "_source": {
          "message": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_id": "4",
        "_score": 0.32951736,
        "_source": {
          "message": "Brown fox brown dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "2",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the lazy dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "3",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the quick dog"
        }
      }
    ]
  }
}

 

2. 일반 must로 fox와 quick단어가 들어가 있는 도큐먼트 검색

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {  "match": {
            "message": "fox"
          }
        },
        {
          "match": {
            "message": "quick"
          }
        }
      ]
    }
  }
}

 

결과

{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 0.9468958,
    "hits": [
      {
        "_index": "my_index",
        "_id": "1",
        "_score": 0.9468958,
        "_source": {
          "message": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_id": "3",
        "_score": 0.87627405,
        "_source": {
          "message": "The quick brown fox jumps over the quick dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "2",
        "_score": 0.6744513,
        "_source": {
          "message": "The quick brown fox jumps over the lazy dog"
        }
      }
    ]
  }
}

 

 

 

3. fox는 그대로 검색하되 filter로 quick을 검색

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "message": "fox"
          }
        }
      ],
      "filter": [
        {
          "match": {
            "message": "quick"
          }
        }
      ]
    }
  }
}

 

결과

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 0.32951736,
    "hits": [
      {
        "_index": "my_index",
        "_id": "1",
        "_score": 0.32951736,
        "_source": {
          "message": "The quick brown fox"
        }
      },
      {
        "_index": "my_index",
        "_id": "2",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the lazy dog"
        }
      },
      {
        "_index": "my_index",
        "_id": "3",
        "_score": 0.23470736,
        "_source": {
          "message": "The quick brown fox jumps over the quick dog"
        }
      }
    ]
  }
}

 

위 실습 정리

마지막 filter를 사용한 검색을 했을 때 결과는 quick과 dog가 모두 포함된 2번 결과와 같은 도큐먼트들이 나오지만
스코어는 fox만 검색했을 때 1번 결과의 스코어와 같다.

=> filter로 검색하는 부분들은 스코어에 영향을 주지 않는다 !

 


범위 쿼리 - Range Query

지금까지 했던 건 문자열 필드의 검색.

ES는 숫자나 날짜 형식들의 저장이 가능. 숫자, 날짜 형식은 range 쿼리를 이용해서 검색.

 

range 쿼리는 range : { <필드명> : <파라미터>:<값> } } 으로 입력.

range 쿼리 파라미터는 아래의 4가지가 있음.

 

  • gte (Greater-than or equal to) - 이상 (같거나 큼)
  • gt ( Greater-than ) - 초과 (큼)
  • lte (Less-than or equal to) - 이하 (같거나 작음)
  • lt (Less-than) - 미만 (작음)

price의 필드 값이 700이상 900미만인 도큐먼트 검색

GET phones/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 700,
        "lt": 900
      }
    }
  }
}

 

날짜 검색

날짜도 숫자와 마찬가지로 range 쿼리의 사용.

es 에서 날짜 값은 2016-01-01 또는 2016-01-01T10:15:30 과 같이 JSON 에서 일반적으로 사용되는 ISO8601 형식.

 

 

date 필드의 날짜가 2016년 1월 1일 이후인 도큐먼트들을 검색

GET phones/_search
{
  "query": {
    "range": {
      "date": {
        "gt": "2016-01-01"
      }
    }
  }
}

 

 

참조 

모든 내용은 아래 가이드 북에서 참고해 공부한 내용...

큰 도움 받았습니다. . . . 

https://esbook.kimjmin.net/05-search/5.6-range

 

5.6 범위 쿼리 - Range Query - Elastic 가이드북

날짜를 검색 할 때는 검색하는 현재 시간을 가져오는 예약어 now와 y(년), M(월), d(일), h(시), m(분), s(초), w(주) 등의 사용이 가능합니다. 다음은 date의 값이 2016년 1월 1일에서 6개월 후인 날 부터 오

esbook.kimjmin.net

 

'공부' 카테고리의 다른 글

Elasticsearch) Mapping  (1) 2023.12.08
Elasticsearch) 데이터 색인과 텍스트 분석  (1) 2023.12.08
Elasticsearch) Query DSL  (1) 2023.12.08
Elasticsearch) CRUD  (1) 2023.12.08
Elasticsearch 활용) 인덱스 샤드 모니터링  (0) 2023.12.07