3 분 소요

[ELK Stack]Elasticsearch 검색 1편 - match, term, bool

1. 검색 쿼리의 구조와 흐름

쿼리 방식 구분

1. 쿼리 스트링 (Query String)

  • REST API의 URL에 파라미터 형식으로 조건을 붙여 검색하는 방식
  • 간단한 테스트나 검색에는 용이하지만 조건이 복잡해질수록 가독성 및 유지보수성이 떨어짐
GET kibana_sample_data_ecommerce/_search?q=customer_full_name:Mary

2. 쿼리 DSL (Query Domain Specific Language)

  • JSON 포맷을 활용하여 REST 요청의 본문(body)에 검색 쿼리를 명시
  • 구조화된 쿼리, 복합 논리 연산, 스코어 조절, 정렬 등 복잡한 조건을 표현할 수 있음
GET kibana_sample_data_ecommerce/_search
{
  "query": {
    "match": {
      "customer_full_name": "Mary"
    }
  }
}

응답 필드 제한

"_source": ["customer_full_name"]
  • 원하는 필드만 응답 결과로 받아올 수 있음 → 데이터 양 절감 및 클라이언트 처리 성능 향상

검색 쿼리의 종류 분류

1. 리프 쿼리 (Leaf Query)

  • 특정 필드에서 조건을 설정하는 가장 기본적인 쿼리
  • ex) match, term, range, multi_match

2. 복합 쿼리 (Compound Query)

  • 여러 쿼리를 논리적으로 조합하는 상위 쿼리 구조
  • ex) bool, function_score, constant_score, dis_max

2. 리프 쿼리 상세 정리

match 쿼리 (전문 검색)

{
  "match": {
    "customer_full_name": "mary bailey"
  }
}
  • text 타입의 필드에서만 사용 가능
  • 분석기(analyzer)를 거쳐 토큰화된 단어 단위로 검색됨 → mary, bailey
  • 기본 연산자는 OR: 두 단어 중 하나만 포함돼도 매칭

operator: and

{
  "match": {
    "customer_full_name": {
      "query": "mary bailey",
      "operator": "and"
    }
  }
}

→ 두 용어 모두 포함되어야 결과 반환

match_phrase 쿼리 (구문 일치 검색)

{
  "match_phrase": {
    "customer_full_name": "mary bailey"
  }
}
  • match 쿼리처럼 분석은 하지만, 단어의 순서와 위치까지 일치해야 결과 반환
  • “mary bailey”는 OK, “bailey mary”는 NO
  • 구문 검색이므로 검색 리소스 많이 사용됨

multi_match 쿼리 (다중 필드 검색)

{
  "multi_match": {
    "query": "mary",
    "fields": [
      "customer_first_name",
      "customer_last_name",
      "customer_full_name"
    ]
  }
}
  • 여러 필드에 대해 동시에 match 검색을 실행
  • 내부적으로 각 필드마다 match 쿼리를 수행하고 가장 높은 score를 대표 score로 반환

와일드카드 필드 선택

"fields": ["customer_*_name"]

boost 가중치 적용

"fields": ["customer_full_name^3", "customer_last_name", "customer_first_name"]
  • 특정 필드에 가중치 부여 → 해당 필드에서 매칭될 경우 스코어 우선 적용

term 쿼리 (정확 일치 검색)

{
  "term": {
    "customer_full_name.keyword": "Mary Bailey"
  }
}
  • 분석기를 거치지 않고 입력 값 그대로 일치 여부 판단
  • 반드시 keyword 타입 필드에서 사용해야 하며, text 필드는 부적절
  • 대소문자 민감함 (Mary ≠ mary)

terms 쿼리 (복수 값

{
  "terms": {
    "day_of_week": ["Monday", "Sunday"]
  }
}
  • SQL의 IN (...) 조건과 유사

range 쿼리 (숫자, 날짜, IP 범위 검색)

{
  "range": {
    "timestamp": {
      "gte": "2020-12-15",
      "lte": "2020-12-16"
    }
  }
}
  • gte, lte, gt, lt 네 가지 연산 지원
  • 날짜/숫자/IP 타입에서만 사용 가능 (keyword/text 타입에서는 불가)

상대 시간 표현

"gte": "now-1M"
  • 상대 시간 표현식: now-1d, now-2h, now-30m 등 (주의: M은 월, 소문자는 시/분/초)

date_range + relation

  • 필드를 date_range 타입으로 매핑한 경우, range 내부에서 relation 속성 사용 가능
relation 설명
intersects 범위가 일부라도 겹치면 매칭
contains 문서 범위가 쿼리 범위를 모두 포함할 경우에만 매칭
within 문서 범위가 쿼리 범위 내에 완전히 속할 경우만 매칭

→ 실무에서 “사용자의 활동 기간이 이 특정 기간을 모두 포함해야 함” 같은 조건 설정 시 유용

3. 복합 쿼리 - bool 쿼리

bool 쿼리 구조

  • 여러 리프 쿼리를 논리 조합하여 검색할 수 있는 가장 기본적인 복합 쿼리

구성 요소

요소 설명 연산 의미 스코어 영향
must 모두 만족해야 매칭 AND 있음
must_not 해당되면 제외 NOT 없음
should 하나라도 만족하면 포함 (or) OR 있음
filter 조건 필터링만, 스코어 영향 없음 - 없음

bool 했던거 모음

must + must_not 조합

{
  "bool": {
    "must": {
      "match": {"customer_full_name": "mary"}
    },
    "must_not": {
      "term": {"customer_last_name": "bailey"}
    }
  }
}

filter 단독 사용 (스코어 계산 없음)

{
  "bool": {
    "filter": {
      "term": {"day_of_week": "Sunday"}
    }
  }
}

must + filter 조합 (성능 최적화)

{
  "bool": {
    "must": {
      "match": {"customer_full_name": "mary"}
    },
    "filter": {
      "range": {
        "products.base_price": {
          "gte": 30,
          "lte": 60
        }
      }
    }
  }
}

should 여러 개 (OR 조건)

{
  "bool": {
    "should": [
      {"term": {"day_of_week": "Sunday"}},
      {"match": {"customer_full_name": "mary"}}
    ]
  }
}

must + should (스코어 향상 용도)

{
  "bool": {
    "must": {"match": {"customer_full_name": "mary"}},
    "should": {"term": {"day_of_week": "Sunday"}}
  }
}

댓글남기기