[elasticsearch] match_all, match, match_phrase 사용 방법 및 차이점
match_all, match, match_phrase 사용 방법 및 차이점
실습 전, 준비사항
test_index에 먼저 bulk로 데이터 입력해주기 & kibana
POST test_index/_bulk
{"index": {"_id":1}}
{"message": "The little cute cat" }
{"index": {"_id":2}}
{"message": "The little cute cat eats the red fish" }
{"index": {"_id":3}}
{"message": "The little cute cat eats the brown fish" }
{"index": {"_id":4}}
{"message": "The cute cat little fish" }
{"index": {"_id":5}}
{"message": "the red fish" }
match_all
match_all은 조건 아무것도 없이 해당 인덱스의 모든 데이터를 검색한다.
GET test_index/_search
{
"query": {
"match_all": {}
}
}
=
GET test_index/_search
kibana에서 모든 데이터를 검색할 때 /_search를 사용하는데 이와 동일하다.
match
Elasticsearch의 풀 텍스트 검색에 가장 보편적으로 사용되는 match query는 말 그대로 "매칭"되는 것을 검색한다.
GET test_index/_search
{
"query": {
"match": {
"message": "cat"
}
}
}
"query"는 항상 써주어야하고 "message" 필드에 "cat"이 포함된 결과들을 보여준다.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 0.32575765,
"hits" : [
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.32575765,
"_source" : {
"message" : "The little cute cat"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "4",
"_score" : 0.30086955,
"_source" : {
"message" : "The cute cat little fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.24476817,
"_source" : {
"message" : "The little cute cat eats the red fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.24476817,
"_source" : {
"message" : "The little cute cat eats the brown fish"
}
}
]
}
}
cat 이 포함된 도큐먼트 총 4개가 나왔다.
첫번째가 두번째보다 점수가 높은 이유는 message 필드의 데이터 길이가 더 짧을 수록 점수가 높게 매겨지기 때문이다.
match "OR"
match query에서 "op" operator 사용하는 방법은 간단하게 스페이스만 추가해주면 된다.
GET test_index/_search
{
"query": {
"match": {
"message": "cat fish"
}
}
}
=
GET test_index/_search
{
"query": {
"match": {
"message": {
"query": "cat fish",
"operator": "or"
}
}
}
}
또는 위와 같이 opderator 를 입력해준다.
쿼리를 실행하면 cat 또는 fish 둘 중 하나라도 포함된 도큐먼트를 모두 검색한다.
{
"took" : 56,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 5,
"relation" : "eq"
},
"max_score" : 0.6017391,
"hits" : [
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "4",
"_score" : 0.6017391,
"_source" : {
"message" : "The cute cat little fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.48953635,
"_source" : {
"message" : "The little cute cat eats the red fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.48953635,
"_source" : {
"message" : "The little cute cat eats the brown fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "5",
"_score" : 0.35513458,
"_source" : {
"message" : "the red fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.32575765,
"_source" : {
"message" : "The little cute cat"
}
}
]
}
}
=> 검색 결과는 5개 전체가 나왔다.
match "AND"
위에서 사용한 Operator에 "or" -> "and"로만 바꿔주면 된다.
GET test_index/_search
{
"query": {
"match": {
"message": {
"query": "cat fish",
"operator": "and"
}
}
}
}
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.6017391,
"hits" : [
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "4",
"_score" : 0.6017391,
"_source" : {
"message" : "The cute cat little fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.48953635,
"_source" : {
"message" : "The little cute cat eats the red fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.48953635,
"_source" : {
"message" : "The little cute cat eats the brown fish"
}
}
]
}
}
=> 결과는 message필드에 cat과 fish를 모두 포함하고 있는 총 3개의 도큐먼트가 나온다.
match_phrase
match_all 은 전체 검색, match는 매칭되는 데이터 검색, match_phrase는 정확한 phrase "구문"을 검색한다.
GET test_index/_search
{
"query":{
"match_phrase": {
"message": "cat eats the red"
}
}
}
message 필드에 정확히 "cat eats the red"라는 문구가 있는 데이터를 검색한다.
결과
{
"took" : 59,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.8085477,
"hits" : [
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.8085477,
"_source" : {
"message" : "The little cute cat eats the red fish"
}
}
]
}
}
match_phrase의 slop 옵션
slop = 1 을 주면 주어진 쿼리의 빈 값에 1 만큼의 다른 단어가 존재해도 괜찮다.
GET test_index/_search
{
"query": {
"match_phrase": {
"message": {
"query": "the fish",
"slop": 1
}
}
}
}
최우선적으로 "the fish" 정확한 데이터가 검색되고 그 다음 "the" + _______ + "fish" 이렇게 있는 데이터가 검색된다. doc5 의 the little fish 를 -> the fish로 수정해서 검색한 결과는
{
"took" : 539,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.41782776,
"hits" : [
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "5",
"_score" : 0.41782776,
"_source" : {
"message" : "the fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.15482008,
"_source" : {
"message" : "The little cute cat eats the red fish"
}
},
{
"_index" : "test_index",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.15482008,
"_source" : {
"message" : "The little cute cat eats the brown fish"
}
}
]
}
}
=> 요렇게 나온다!
검색 쿼리가 "the little cat"이고 slop = 1 이라면 " " 스페이스 값(?) 빈 스트링 값 (?) 이 있는 곳 중 1 곳만 다른 단어가 들어오는 데이터를 검색한다.
ex1. the very little cat ----- ok
ex2. the little cute cat ----- ok
ex3. the very little cute cat ----- X
만약 slop = 2 로 하면 위의 3번째 예시도 가능하다. 2번 slop을 할 수 있으니 !
결론 :
모든 검색결과는 - match_all 을,
매칭되는 검색 또는 교집합/합집합 검색결과는 match 사용
정확한 String값 매칭 - match_phrase 사용하기 !
Reference : https://esbook.kimjmin.net/05-search/5.1-query-dsl