_search API로 검색하기
_search API로 검색하기
검색은 하나 이상의 쿼리를 조합해 Elasticsearch로 보내는 일이에요. 쿼리에 맞는 문서는 응답의 hits, 즉 검색 결과로 돌아오죠. Elasticsearch의 검색 REST API인 _search는 데이터 스트림이나 인덱스에 저장된 데이터를 검색하고 집계까지 처리해요. 요청 바디의 query 파라미터에는 쿼리 DSL 문법으로 쿼리를 적어 넣어요.
검색 실행하기
가장 기본적인 예를 볼게요. 아래 요청은 my-index-000001 인덱스에서 user.id 값이 kimchy인 문서를 찾아요. match 쿼리를 쓰고 있죠.
{
"query": {
"match": {
"user.id": "kimchy"
}
}
}
API 응답은 쿼리에 맞는 상위 10개 문서를 hits.hits 속성에 담아 돌려줘요. 이렇게 검색은 /index/_search 같은 REST 엔드포인트에 JSON 바디를 실어 보내면 됩니다.
공통 검색 옵션
검색을 입맛대로 다듬을 수 있는 옵션들도 있어요.
- 쿼리 DSL —
bool같은 복합 쿼리, 정확한 일치를 찾는 term-level 쿼리, 검색 엔진에서 흔히 쓰는 전체 텍스트 쿼리, 지리·공간 쿼리를 섞어 쓸 수 있어요. - 집계 (Aggregations) — 검색 결과에서 통계·분석을 얻어요. "필드별 문서 수", "평균 · 합계" 같은 질문에 답해 주죠.
- 여러 스트림·인덱스 검색 — 쉼표 구분 값과 grep 같은 인덱스 패턴으로 여러 데이터 스트림과 인덱스를 한 요청에 검색할 수 있어요. 특정 인덱스의 결과에 부스트를 줄 수도 있어요.
- 페이징 — 기본적으로 검색은 상위 10개의 히트만 돌려줘요. 더 많거나 적은 문서가 필요하면 페이징 옵션으로 조절해요.
- 필드 선택 —
hits.hits는 각 히트의 전체_source를 포함해요. 필요한 필드만 골라 받으려면 필드 선택 옵션을 써요. - 정렬 — 기본 정렬은 관련성 점수
_score기준이에요.script_score쿼리로 점수 계산을 바꾸거나, 다른 필드 값으로 정렬할 수도 있어요.
검색 타임아웃
기본적으로 검색 요청은 타임아웃이 없어요. 모든 샤드에서 완료 결과가 올 때까지 기다리죠. timeout 값을 설정하면 샤드 단위로 적용돼요. 어느 샤드에서 타임아웃을 넘기면 일부 결과만 돌아오고, 응답에 "timed_out": true가 표시돼요.
{
"took": 11,
"timed_out": true,
"_shards": {
"total": 40,
"successful": 40,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 98393,
"relation": "eq"
}
}
}
전체 요청이 부분 결과 대신 오류로 끝나야 한다면 default_allow_partial_results를 false로 두면 돼요. 모든 검색에 걸리는 기본 타임아웃을 클러스터 단위로 정하고 싶다면 search.default_search_timeout 설정을 쓸 수 있어요.
동기 vs 비동기 검색
Elasticsearch 검색은 방대한 데이터를 빠르게 처리하도록 설계돼서, 기본은 동기(synchronous) 예요. 요청이 완료 결과를 받아 오기 전까지 기다리죠. 그런데 큰 데이터 세트나 여러 클러스터를 오가는 검색은 완료까지 오래 걸릴 수 있어요. 이때는 비동기(async) 검색을 써서, 지금은 부분 결과를 먼저 받고 나중에 완료 결과를 가져올 수 있어요.
정확한 히트 수 추적
총 히트 수는 모든 일치 문서를 방문해야 정확히 계산되니, 많은 문서에 걸린 쿼리에서는 비용이 커요. track_total_hits 파라미터로 총 히트 수를 어떻게 추적할지 제어할 수 있어요. 기본값은 10,000으로, 그 지점까지는 정확히 세고 그 뒤로는 하한만 알려줘요. 성능과 정확도의 트레이드오프를 조절하는 셈이죠.
true로 두면 항상 정확히 셉니다.total.relation이 항상"eq"가 돼요.- 숫자로 주면 해당 개수까지 정확히 추적해요. 예를 들어 100까지 정확히 세고 싶다면 이렇게요.
{
"track_total_hits": 100,
"query": {
"match": {
"user.id": "elkbee"
}
}
}
응답의 hits.total.relation이 정확한 값("eq")인지 하한 값("gte")인지 알려줘요. 보통은 어느 선 이상의 정확한 수치가 필요 없을 때가 많아서, track_total_hits를 낮출수록 쿼리가 빨라지고 false가 가장 빠르답니다.
일치 문서가 있는지만 빠르게 확인
결과 자체가 아니라 '일치하는 문서가 있는지'만 궁금할 때가 있어요. 이때는 size를 0으로 두면 결과는 돌려주지 않고 히트 수만 확인할 수 있어요. terminate_after를 1로 두면 샤드마다 첫 번째 일치 문서를 찾는 즉시 쿼리 실행을 끝내요. 응답에 terminated_early: true가 표시되고, 얼마나 빨리 종료됐는지 알 수 있어요.
더 알아보기
- Elasticsearch에서 검색 인터페이스 고르기 — Query DSL·Retrievers·ES|QL의 전체 비교
- 쿼리 DSL —
query파라미터에 담는 쿼리 언어