본문으로 건너뛰기
김신건의 로그

[Search] ES Query: must / should / filter / must_not

· 수정 · 📖 약 1분 · 446자/단어 #elasticsearch #query #bool #search
ES query, bool query, must, should, filter, must_not, match, term, range, query DSL, ESQL

정의

ES 의 Query DSL = JSON 기반 표현력 풍부한 쿼리 언어. bool query + leaf query 의 조합.

bool query: 4가지 절

flowchart LR
    Bool[bool query]
    Bool --> Must["must<br/>(AND, score 계산)"]
    Bool --> Should["should<br/>(OR, score 가산)"]
    Bool --> Filter["filter<br/>(AND, score 없음)"]
    Bool --> MustNot["must_not<br/>(NOT, score 없음)"]
AND/ORScoreCache
mustAND안됨
shouldOR예 (가산)안됨
filterAND없음예 (빠름!)
must_notNOT없음

IMPORTANT

Score 가 필요 없으면 항상 filter. must + 동일 조건보다 압도적으로 빠름 (cache + scoring 생략).

종합 예시

GET /products/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "mechanical keyboard" } }
      ],
      "should": [
        { "match": { "tags": "rgb" } },
        { "match": { "tags": "wireless" } }
      ],
      "filter": [
        { "term": { "category": "input-device" } },
        { "range": { "price": { "gte": 50, "lte": 200 } } },
        { "term": { "in_stock": true } }
      ],
      "must_not": [
        { "term": { "brand": "Brand-X" } }
      ],
      "minimum_should_match": 1
    }
  }
}

해석:

  1. title“mechanical keyboard” 매칭 (필수, score 계산)
  2. tags“rgb” 또는 “wireless” 있으면 가산 (minimum_should_match: 1 적용)
  3. category, 가격 50-200, 재고 있음 (필터, 빠름)
  4. Brand-X 제외

leaf query 카테고리

flowchart TB
    Q[Leaf Queries]
    Q --> FullText[Full Text]
    Q --> TermLevel[Term Level]
    Q --> Range[Range]
    Q --> Geo[Geo]
    Q --> Vector[Vector / Semantic]
    Q --> Compound[Compound]
    FullText --> M1[match, match_phrase, multi_match, match_phrase_prefix, query_string, simple_query_string]
    TermLevel --> T1[term, terms, exists, prefix, wildcard, regexp, fuzzy, ids]
    Range --> R1[range]
    Geo --> G1[geo_distance, geo_bounding_box, geo_polygon]
    Vector --> V1[knn, sparse_vector, text_expansion]
    Compound --> C1[bool, dis_max, constant_score, function_score]

match vs term

// match: 분석기 적용 → tokenized 비교
{ "match": { "title": "Mechanical Keyboard" } }
// → tokens: ["mechanical", "keyboard"]
// → 둘 중 하나라도 매칭 (operator=or 기본)

// term: 분석 없이 *exact* (keyword 필드용)
{ "term": { "status": "active" } }

CAUTION

text 필드에 term 쿼리 = 원본 토큰 못 찾음 (분석기가 lowercase 등 했기 때문). textmatch, keywordterm.

match_phrase + slop

{ "match_phrase": { "title": { "query": "mechanical keyboard", "slop": 1 } } }
  • 연속된 토큰 매칭.
  • slop: 얼마나 떨어져도 OK (단어 거리).

multi_match

{
  "multi_match": {
    "query": "rabbit hat",
    "fields": ["title^3", "description", "tags"]
  }
}
  • 여러 필드 동시 검색.
  • field^N: 가중치.
  • type: best_fields, most_fields, cross_fields, phrase.

function_score (커스텀 ranking)

{
  "query": {
    "function_score": {
      "query": { "match": { "title": "keyboard" } },
      "functions": [
        { "filter": { "term": { "premium": true } }, "weight": 2.0 },
        { "field_value_factor": { "field": "popularity", "modifier": "log1p" } },
        { "gauss": { "created_at": { "origin": "now", "scale": "30d", "decay": 0.5 } } }
      ],
      "boost_mode": "multiply"
    }
  }
}
function의미
weight상수 곱
field_value_factor필드값 기반 (popularity 등)
gauss / linear / exp거리 기반 감쇠 (시간, 위치)
script_scorePainless 스크립트
random_score무작위 (A/B)

ESQL (2024 GA)

SQL 같은 파이프 표기:

FROM logs-*
| WHERE @timestamp > NOW() - 7 days AND status_code >= 500
| STATS error_count = COUNT(*) BY service.name, host.name
| SORT error_count DESC
| LIMIT 20

TIP

DSL 의 복잡함 회피. 2026 시점 대시보드 / ad-hoc 쿼리 에서 ESQL 이 표준. Kibana 의 default 쿼리도 ESQL 전환 중.

동작 흐름

일반 검색 직관. ES 도 같은 query → ranking → top-K 흐름.

흔한 함정

WARNING

  1. textterm = 매칭 0. keyword field 사용 또는 match.
  2. should 만 사용 = minimum_should_match 누락 → 0개 일치 OK. 명시 권장.
  3. score 불필요한데 must = cache 못 씀. filter 로.
  4. wildcard, regexp, prefix 남용 = 느림. 분석기 변경 + edge_ngram 으로 대체.

관련 위키

이 글의 용어 (4개)
[Search] ES Aggregations: metric, bucket, pipelinesearch
정의 Aggregations (aggs) = ES 의 집계 분석. SQL 의 GROUP BY + 함수 + window. 검색 결과 또는 전체 위에서. 3가지 카테고리 Metric…
[Search] ES Mapping: field type, dynamic, multi-fieldsearch
정의 Mapping = ES 의 schema. 각 필드의 type + analyzer + indexing 옵션. 대부분 immutable (재인덱싱 필요). Field Type …
[Search] ES Relevance Scoring: BM25, TF-IDF, function_scoresearch
정의 Relevance Score ( ) = 쿼리와 문서의 매칭 강도. ES 7+ 의 기본은 BM25 (TF-IDF 의 발전형). BM25 공식 | 부분 | 의미 | |---|-…
[Search] ES Vector Search: kNN, ELSER, RAGsearch
정의 ES 의 벡터 검색 = 임베딩 기반 의미 검색. kNN (Approximate Nearest Neighbor) 으로 수억 벡터 안에서 가까운 K개 찾기. 2026 시점의 E…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기