4.4 검색 API - _search API

이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍니다.

지금까지는 도큐먼트 단위의 입력, 수정, 삭제, 조회 하는 방법을 알아보았습니다. 하지만 Elasticsearch의 진가는 쿼리를 통한 검색 기능에 있습니다. 검색은 인덱스 단위로 이루어집니다. GET <인덱스명>/_search 형식으로 사용하며 쿼리를 입력하지 않으면 전체 도큐먼트를 찾는 match_all 검색을 합니다.

URI 검색

_search 뒤에 q 파라메터를 사용해서 검색어를 입력할 수 있습니다. 이렇게 요청 주소에 검색어를 넣어 검색하는 방식을 URI 검색이라고 합니다.

앞에서 만든 test 인덱스에서 "value" 라는 값을 검색하기 위해서는 다음과 같이 입력합니다.

request
response
request
URI 검색으로 검색어 "value" 검색
GET test/_search?q=value
response
URI 검색으로 검색어 "value" 검색 결과
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.105360515,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.105360515,
"_source" : {
"field" : "value three"
}
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.105360515,
"_source" : {
"field" : "value two"
}
}
]
}
}

결과를 보면 hits.total.value 부분에 검색 결과 전체에 해당되는 문서의 개수가 표시되고 다시 그 안의 hits:[ ] 구문 안에 배열로 가장 정확도가 높은 문서 10개가 나타납니다. 이 정확도를 relevancy(렐러번시 라고 읽습니다) 라고 하며 뒤에서 다시 설명하도록 하겠습니다.

두 개의 검색어 "value" 그리고 "three"AND 조건으로 검색 하려면 다음과 같이 입력합니다. URI 쿼리에서는 AND, OR, NOT 의 사용이 가능하며 반드시 모두 대문자로 입력해야합니다.

request
response
request
URI 검색으로 검색어 "value AND three" 검색
GET test/_search?q=value AND three
response
URI 검색으로 검색어 "value AND three" 검색 결과
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.87546873,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.87546873,
"_source" : {
"field" : "value three"
}
}
]
}
}

valuethree 를 모두 포함한 test/_doc/3 도큐먼트 만이 결과로 리턴되었습니다. 검색어 value 을 field 필드에서 찾고 싶으면 다음과 같이 <필드명>:<검색어> 형태로 입력합니다. 검색은 항상 필드를 지정해서 하는 것이 좋습니다.

request
response
request
URI 검색으로 "field" 필드에서 검색어 "value" 검색
GET test/_search?q=field:value
response
URI 검색으로 "field" 필드에서 검색어 "value" 검색 결과
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.18232156,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.18232156,
"_source" : {
"field" : "value three"
}
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.18232156,
"_source" : {
"field" : "value two"
}
}
]
}
}

URI 검색은 루씬의 기본 쿼리 문법을 사용하며 손쉽게 다룰 수 있습니다. 또한 웹 브라우저 주소창 등에서도 사용 가능하기 때문에 빠르게 쓰긴 쉬우나 좀 더 복잡한 검색을 위해서는 다음에 설명하는 데이터 본문(data body) 검색을 이용해야 합니다.

데이터 본문 (Data Body) 검색

데이터 본문(data body) 검색은 검색 쿼리를 데이터 본문으로 입력하는 방식입니다. Elasticsearch의 QueryDSL을 사용하며 쿼리 또한 Json 형식으로 되어 있습니다. 처음 익힐때는 다소 복잡 해 보일 수 있으나 주로 사용하는 쿼리 몇가지들 부터 차근 차근 익혀나가면 크게 어렵지 않게 사용이 가능합니다.

가장 쉽고 많이 사용되는 것은 match 쿼리입니다. 여기서는 문법만 살펴보고 다음 검색 장에서 더 많은 쿼리들에 대해 자세히 다뤄보도록 하겠습니다. 데이터 본문 검색으로 field 필드값이 value 인 도큐먼트를 검색하기 위해서는 다음 명령을 실행합니다.

request
response
request
데이터 본문 검색으로 "field" 필드에서 검색어 "value" 검색
GET test/_search
{
"query": {
"match": {
"field": "value"
}
}
}
response
데이터 본문 검색으로 "field" 필드에서 검색어 "value" 검색 결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.105360515,
"hits" : [
{
"_index" : "test",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.105360515,
"_source" : {
"field" : "value three"
}
},
{
"_index" : "test",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.105360515,
"_source" : {
"field" : "value two"
}
}
]
}
}

쿼리 입력은 항상 query 지정자로 시작합니다. 그 다음 레벨에서 쿼리의 종류를 지정하는데 위에서는 match 쿼리를 지정했습니다. 그 다음은 사용할 쿼리 별로 문법이 상이할 수 있는데 match 쿼리는 <필드명>:<검색어> 방식으로 입력합니다.

멀티테넌시 (Multitenancy)

Elasticsearch는 여러 개의 인덱스를 한꺼번에 묶어서 검색할 수 있는 멀티테넌시를 지원합니다.logs-2018-01, logs-2018-02 … 와 같이 날짜별로 저장된 인덱스들이 있다면 이 인덱스들을 모두 logs-*/_search 명령으로 한꺼번에 검색이 가능합니다. 특히 시간순으로 따라 쌓이는 로그 데이터를 다룰 때는 인덱스를 일단위 등으로 구분하는것이 좋습니다. 나중에 필드 구조가 변경되거나 크기가 커져서 샤드 설정을 변경하거나 할 때 더욱 용이합니다.

여러 인덱스를 검색할때는 쉼표, 로 나열하거나 와일드카드 * 문자로 묶을 수 있습니다.

쉼표로 나열해서 여러 인덱스 검색
GET logs-2018-01,2018-02,2018-03/_search
와일드카드 * 를 이용해서 여러 인덱스 검색
GET logs-2018-*/_search

인덱스명 대신 _all 지정자를 사용하여 GET _all/_search 와 같이 실행하면 클러스터에 있는 모든 인덱스를 대상으로 검색이 가능합니다. 하지만 _all은 시스템 사용을 위한 인덱스 같은 곳의 데이터까지 접근하여 불필요한 작업 부하를 초래하므로 _all 은 되도록 사용하지 않도록 합니다.