2025. 8. 25. 16:38ㆍBig Data
es에서는 아래의 명령을 호출해서 해당 index에 검색 요청을 할 수가 있다.
SEARCH
아래의 명령은 title field에 test라는 단어가 들어 있는 문서에 대해 검색 요청을 진행했다.
$> curl -X GET "localhost:9200/test/_search?q=title:test&pretty"
url이 아닌 body 형태로도 명령을 호출할 수 있다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"term" : { "title" : "test" }
}
}
'
SORTING
검색 결과에 대한 sorting도 진행 할 수 있다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"sort" : [
{ "id" : "desc" }
],
"query" : {
"term" : { "title" : "test" }
}
}
'
SOURCE
검색 결과에 모든 필드가 아닌 필요한 필드만 가져오고 싶을 땐 source를 사용한다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"_source" : [ "title", "content" ],
"query" : {
"term" : { "title" : "test" }
}
}
'
HIGHTLIGHT
hightlight 옵션을 통해 어느 부분이 query 결과에 일치했는지를 확인할 수 있다. hightlight 옵션을 통해 검색 결과 중 어떤 필드에 hightlight 효과를 줄 수 있는지 지정할 수 있다. 아래의 예에서는 title field에 강조하도록 명시되어 있다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"term" : { "title" : "test" }
},
"hightlight" : {
"fields" : { "title" : {} }
}
}
'
BOOST
검색 결과의 score 값을 높이거나 낮추기 위해 boost 옵션을 사용할 수가 있다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"match" : {
"title" : {
"query" : "test",
"boost" : 2
}
}
}
}
'
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"term" : {
"title": {
"value" : "nginx",
"boost" : 2
}
}
}
}
'
term을 사용할 경우와 match를 사용할 경우에 대한 format이 달라진 다는 것에 유의하자.
여기서 term과 match의 차이점!!
match의 경우는 analyzer가 있는 경우 analyzer가 적용되는 질의를 말한다. 예를 들어 '나는 학교에 간다'라는 질의를 던졌고, title이 standard analyzer가 적용이 되어 있다면 질의는 나는, 학교에, 간다 라는 질의가 각각 던져지고 이 세 단어중 하나라도 존재하는 문서라면 검색이 된다. 주로 text field에 많이 사용된다.
term의 경우는 match와 약간 다르다. term은 analyzer가 적용이 되지 않고 exact하게 매칭이 되어야만 검색이 된다. 위에서 예로 든 '나는 학교에 간다'라는 문장이 정확히 존재하는 문서만 검색이 된다. 주로 keyword field에 많이 사용된다.
term의 경우 value field가 match의 경우 query field가 사용된다는 것에 주의하자.
SCROLL
scroll 옵션을 통해서 pagination 효과를 얻을 수 있다. 기존 from/size를 통한 기존 pagination과의 차이라고 한다면, scroll을 적용한 시점의 데이터를 snapshot 한다는 것이다. 만약에 from/size를 통한 pagination을 한다면, 요청 중간에 새롭게 색인된 데이터 때문에 기존의 pagination 결과가 변경이 될 수 있다. 하지만 scroll의 경우 해당 시점의 snapshot이기 때문에 freezing 된 상태의 데이터를 얻을 수 있다. 주의할 사항은 scroll의 경우 유지 기간을 지정하도록 되어 있는데 해당 기간이 지나치게 길다면 heap memory 사용량이 늘어날 수 있으니 주의하도록 하자.
# 첫 번째 데이터 가져오기
$> curl -X POST "localhost:9200/test/_search?scroll=1m&pretty" -H 'Content-Type: application/json' -d'
{
"size" : 1,
"query": {
"match" : { "title" : "test" }
}
}
'
# 이 후 데이터부터는 첫 번째 데이터 결과로 받아온 scroll_id를 이용해서 가져온다.
$> curl -X POST "localhost:9200/_search/scroll?pretty" -H 'Content-Type: application/json' -d'
{
"scroll" : "1m",
"scroll_id" : "xxxx.....xxxxxx"
}
'
QUERY DSL
검색 query의 종류에 대해 보다 상세하게 알아보도록 한다.
match
위에서도 잠깐 언급됐었던 match query는 검색어로 들어온 데이터에 대해 analyzer를 통해 tokenizing을 한 후 각각의 token을 가지고 있는 문서를 검색하는 역할을 한다. token의 순서는 score ranking에 영향을 끼치지 않는다. 예를 들어 '나는 학교에 간다'라는 query가 입력되었을 때, 검색 결과는 '나는', '학교에', '간다' 라는 단어가 가장 많이 내포되어 있는 문서를 score 값이 높게 리턴한다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match" : { "title" : "test" }
}
}
'
match_phrase
match_phrase는 match와 비슷하지만 query의 순서를 보장한다는 특징이 있다. 아래의 예를 보자.
title field에 대해 test title이라는 query를 요청하게 되면, es에서는 test title이라는 정확한 순서를 포함하고 있는 문서를 검색하게 된다. 두 token 중 하나만 가지고 있거나 순서가 다른 경우에는 검색 결과에 포함되지 않는다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match" : { "title" : "test title" }
}
}
'
multi_match
두 개 이상의 field에 query를 요청할 수 있다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"multi_match" : {
"query" : "test",
"fields" : [ "title", "content" ]
}
}
}
'
query_string
루씬의 검색 문법을 이용하고 싶을 때, query_string을 사용할 수가 있다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"query_string" : {
"field" : [ "title" ],
"query" : "(test1 AND test2) OR \"test3\""
}
}
}
'
term
정확하게 일치하는 단어를 찾을 때 사용한다. analyze를 거치지 않기 때문에 대소문자를 구분해야 한다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"term" : { "title" : "Test" }
}
}
'
range
특정 범위 내의 값을 찾고자 할 때 사용한다.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"range" : {
"date" : {
"gte" : "2025-08-25",
"lte" : "2025-08-26"
}
}
}
}
'
wildcard
wildcard(*)를 이용한 검색 쿼리이다. keyword type에만 적용이 가능하다. wildcard는 full text scan이기 때문에 검색 성능에 상당한 영향을 끼친다. 되도록 match 쿼리를 사용해서 문제를 해결하도록 하자.
$> curl -X GET "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"wildcard" : { "title.keyword" : "*test*" }
}
}
'
bool query
위에서 살펴본 query 들에 대해 두 가지 이상의 query를 조합해서 적용하는 방법을 알아보도록 한다. 아래는 match query와 range query를 조합한 예시이다. must와 filter의 경우 query에 대해 일치하는 문서를 검색하는 기능은 똑같지만 must의 경우 scoring을 하고 caching을 하지 않는 반면에, filter는 scoring을 하지 않고, caching을 하는 차이가 있다. 만약에 구지 ranking 작업이 필요하지 않는 검색이라면 filter option을 써서 검색하는 것이 더 검색 성능을 빠르게 할 수 있다. (filter option은 range, term, wildcard 등에서 사용이 가능하다. analyze가 적용이 안되는 검색 query)
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"bool" : {
"must" : [{
"match" : { "title" : "test" }
}],
"filter" : [{
"range" : {
"date" : {
"gte" : "2025-08-25",
"lte" : "2025-08-26"
}
}
}]
}
}
}
'
must_not option을 통해 원하는 않는 단어가 들어 있는 문서를 제외 시킬 수도 있다. must_not의 경우도 filter와 마찬가지로 scoring을 하지 않으며 문서 caching을 하는 특징을 가지고 있다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"bool" : {
"must" : [{
"match" : { "title" : "test" }
}],
"filter" : [{
"range" : {
"date" : {
"gte" : "2025-08-25",
"lte" : "2025-08-26"
}
}
}],
"must_not" : [{
"match" : { "content" : "test" }
}]
}
}
}
'
마지막으로 살펴볼 option은 should이다. should option을 통해 boost 효과를 낼 수 있으며, 최소한 반드시 포함되어야 할 단어도 지정할 수가 있다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"bool" : {
"must" : [{
"match" : { "title" : "test" }
}],
"should" : [{
"match": { "title" : "test1"}
}]
}
}
}
'
위와 같이 호출하게 되면 title이 test를 포함하고 있는 문서를 es에서는 리턴해주게 된다. 하지만 만약에 해당 문서에 title에 test1이라는 단어가 포함되어 있다면 score를 높여주는 효과를 가지게 된다. 이처럼 검색 랭크에 변화를 주기 위한 용도로 should를 사용할 수 있다.
또한 아래와 같이 어떤 단어는 반드시 포함되었으면 하는 경우에도 should를 사용할 수 있다.
$> curl -X POST "localhost:9200/test/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query" : {
"bool" : {
"must" : [{
"match" : { "title" : "test" }
}],
"should" : [{
"match" : { "title" : "test1" }
},
{ "match" : { "title" : "test2" }
}],
"minumum_should_match" : 1
}
}
}
'
minumum_shoud_match : 1 이라는 파라미터를 통해 should option에서 지정한 단어 중 1개는 반드시 해당 field에 존재해야 한다.