엘라스틱서치는 검색에 뛰어난 성능을 보이기 때문에 지원하는 쿼리의 종류도 많습니다. 구글링을 통해 손쉽게 사용할 수 있지만 어떤 상황에 어떤 쿼리를 사용해야 할지 미리 알고 있다면 찾는 수고로움도 줄어들 것입니다. 이번에는 엘라스틱서치의 기본 쿼리에 대해 알아보겠습니다.
1. 검색 대상 지정
엘라스틱서치는 다양한 종류의 검색 쿼리를 제공하지만, 그중 어떤 쿼리를 사용해도 동일한 검색 API를 사용합니다. 사용되는 API는 다음과 같습니다.
GET [인덱스 이름]/_search
POST [인덱스 이름]/_search
GET _search
POST _search
인덱스 이름을 지정하지 않으면 전체 인덱스에 대해서 검색합니다. 성능적인 부담이 되므로 인덱스 이름을 지정해서 쿼리를 날리는 것을 권장합니다. 인덱스 이름에는 와일드카드 문자 *를 사용할 수 있고 콤마를 사용해서 검색 대상을 여러 개 지정하는 것도 가능합니다.
GET my_index*,analyzer_test*,mapping_test/sesarch
2. match_all 쿼리
match_all 쿼리는 모든 문서를 검색하는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"match_all": {}
}
}
이렇게 사용해도 되고, 그냥 간단하게 다음과 같이 사용해도 됩니다.
GET [인덱스 이름]/_search
3. match 쿼리
match 쿼리는 풀 텍스트 검색에 사용되는 가장 일반적인 쿼리입니다. 지정한 필드의 내용이 질의어와 매치되는 문서를 찾는 쿼리입니다. 검색어에 애널라이저를 적용하여 dog라고 검색해도 dogs가 포함된 문서를 찾게 할 수 있습니다.
다음은 match 쿼리를 사용하여 해당 인덱스에서 "message" 필드에 "dog"가 포함되어 있는 모든 문서를 검색합니다.
GET [인덱스 이름]/_search
{
"query": {
"match": {
"message": "dog"
}
}
}
match 검색에 여러 검색어를 넣으면 디폴트로 OR 조건으로 검색이 됩니다. 이렇게 하면 입력된 검색어 별로 하나라도 포함된 모든 문서를 탐색합니다.
다음은 검색어로 "quick dog"를 검색합니다. "quick"과 "dog"중 어떤 단어라도 포함된 문서가 검색됩니다.
GET [인덱스 이름]/_search
{
"query": {
"match": {
"message": "quick dog"
}
}
}
OR 조건이 아닌 AND 조건으로 검색을 한다면 operator 옵션을 사용해야 합니다. 이렇게 하면 모든 텀이 매치된 문서만 검색되도록 변경할 수 있습니다. 다만 OR 검색과는 조금 다른 것이 <필드명> : {"query": <검색어>, "operator": "and" } 방식으로 변경됩니다. 여기 operator에 or을 지정하면 OR검색도 가능합니다.
다음은 검색어로 "quick dog"를 검색합니다. 이번에는 "quick dog"를 모두 포함한 문서만 검색됩니다.
GET [인덱스 이름]/_search
{
"query": {
"match": {
"message": {
"query": "quick dog",
"operator": "and"
}
}
}
}
4. term 쿼리
term 쿼리는 지정한 필드의 값이 질의어와 정확히 일치하는 문서를 찾는 쿼리입니다. match 쿼리와 유사하다고 느낄 수 있겠지만 term 쿼리는 match 쿼리와 달리 입력된 검색어에 애널라이저를 적용하지 않습니다. 따라서 dogs라는 문서에 dog라고 검색하면 해당 문서가 나타나지 않습니다.
다음은 term 쿼리를 사용해 "dog"를 검색합니다.
GET [인덱스 이름]/_search
{
"query": {
"term": {
"message": "dog"
}
}
}
5. terms 쿼리
terms 쿼리는 term 쿼리와 매우 유사합니다. term 쿼리와 같이 지정한 필드의 값이 질의어와 정확히 일치하는 문서를 찾지만, 대신 질의어를 여러 개 지정할 수 있습니다. 하나 이상의 질의어가 일치하면 검색 결과에 포함됩니다.
다음은 terms 쿼리를 이용하여 "quick", "dog"를 검색합니다.
GET [인덱스 이름]/_search
{
"query": {
"terms": {
"message": ["quick", "dog"]
}
}
}
6. range 쿼리
지금까지는 문자열 필드들의 검색이었고, range 쿼리는 조금 다릅니다. 숫자, 날짜 형식은 range 쿼리를 이용하여 검색을 합니다. 지정한 필드의 값이 특정 범위 내에 있는 문서를 찾는 쿼리입니다.
다음은 "price" 값이 700 이상 900 미만인 데이터를 검색하는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"range": {
"price": {
"gte": 700,
"lt": 900
}
}
}
}
범위는 아래의 4가지가 있습니다.
- gte (Greater-than or equal to): 이상
- lte (Less-than or equal to): 이하
- lt (Less-than): 미만
- gt (Grater-than): 초과
날짜도 숫자와 마찬가지로 range 쿼리 사용이 가능합니다. 기본적으로 날짜 값은 2016-01-01 또는 2016-01-01T10:15:30 과 같이 JSON에서 일반적으로 사용되는 ISO8601 형식을 사용합니다.
다음은 "date" 필드의 날짜가 2016년 1월 1일에서 6개월 후인 날 부터 오늘보다 365일 전인 날 사이의 데이터를 가져오는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"range": {
"date": {
"gt": "2016-01-01||+6M",
"lt": "now-365d"
}
}
}
}
날짜 시간 계산에는 다음과 같은 표현이 사용됩니다.
- now: 현재 시간을 나타냄
- +와 -: 지정된 시간만큼 더하거나 빼는 연산을 수행함
- - /: 버림을 수행함.
- - ||: 날짜 시간 문자열의 마지막에 붙임. 이 뒤의 문자열은 시간 계산식으로 파싱 됨
7. prefix 쿼리
prefix 쿼리는 필드의 값이 지정한 질의어로 시작하는 문서를 찾는 쿼리입니다.
다음은 "user.id" 필드가 "ki"로 시작하는 문서를 찾는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"prefix": {
"user.id": {
"value": "ki"
}
}
}
}
8. exists 쿼리
exists 쿼리는 지정한 필드를 포함한 문서를 검색합니다.
다음은 "field"에서 "user"를 포함한 문서를 찾는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"exists": {
"field": "user"
}
}
}
9. bool 쿼리
bool 쿼리는 여러 쿼리를 조합하여 검색하는 쿼리입니다. must, must_not, filter, should의 4가지 조건절에 다른 쿼리를 조합하여 사용합니다.
다음은 단어 "quick"과 구문 "lazy dog"가 포함된 모든 문서를 검색하는 쿼리입니다.
GET [인덱스 이름]/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"message": "quick"
}
},
{
"match_phrase": {
"message": "lazy dog"
}
}
]
}
}
}
bool 쿼리의 4개의 인자는 다음과 같습니다.
- must: 쿼리가 참인 도큐먼트 검색
- must_not: 쿼리가 거짓인 도큐먼트 검색
- should: 검색 결과 중 이 쿼리에 해당하는 도큐먼트의 점수를 높임
- filter: 쿼리가 참인 도큐먼트를 검색하지만 스코어를 계산하지 않음. must보다 검색 속도가 빠르고 캐싱이 가능함