[ElasticSearch 정리하기] Full Text Search 종류
출처: https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html
출처: https://stackoverflow.com/questions/26001002/elasticsearch-difference-between-term-match-phrase-and-query-string
1. term
하나의 term을 찾는다. 이 term은 analyze 되지 않는다. 따라서 대소문자, 복수형 등이 다 구분된다
{ "user":"Bennett" }
{
"query": {
"term" : { "user" : "bennett" }
}
}
//아무것도 리턴되지 않는다. (대소문자 구분)
2. match
가장 기본적인 search로 text, number, date, boolean을 사용할 수 있다. text는 검색하기전 analyze된다.
fuzzy matching을 지원한다(정확하게 일치하지않더라도 연관성이 있다고 판단하면 리턴).
GET /_search
{
"query": {
"match" : {
"message" : {
"query" : "this is a test"
}
}
}
}
3. query_string
입력값을 analyze한다. 사용자가 명시적으로 ""로 둘러싸지않는이상 순서는 상관이 없다.
{ "foo":"I just said hello world" }
{ "foo":"Hello world" }
{ "foo":"World Hello" }
{
"query": {
"query_string": {
"query": "hello World"
}
}
}
//얘는 3개를 다 리턴한다
{
"query": {
"query_string": {
"query": "\"Hello World\""
}
}
}
//얘는 명시적으로 ""로 싸여져 있기 때문에 match_phrase와 동일하게 처음 2개만을 리턴한다.
query_string과 match의 차이점은 AND와 OR같은 연산자를 사용할 수 있다.
query_string은 syntax를 먼저 parse한 뒤에 split을 하고 analyze를 한다.
GET /_search
{
"query": {
"query_string" : {
"query" : "(new york city) OR (big apple)",
"default_field" : "content"
}
}
}
주의할 점: query_string은 invalid syntax에 대해 에러를 반환하므로 AND와 OR과 같은 query syntax를 지원해야되는 것이 아니라면 match를 사용하거나 좀 더 덜 엄격한 simple_query_string을 사용하는 것이 낫다.
4. Intervals
matching rules를 사용하여 쿼리한다. 여러개의 term들이 원하는 간격안에 존재하는지 쿼리한다.
아래의 쿼리는 "hot"과 "porridge"사이에 10단어 이상 간격이 없으면서 중간에 "salty"가 없어야 된다.
POST _search
{
"query": {
"intervals" : {
"my_text" : {
"match" : {
"query" : "hot porridge",
"max_gaps" : 10,
"filter" : {
"not_containing" : {
"match" : {
"query" : "salty"
}
}
}
}
}
}
}
}
5. match_phrase
입력값을 analyze한다. 그리고 다음의 조건을 충족하는 document를 찾아서 반환한다.
- 모든 term들이 field에 존재해야한다.
- 모든 term들이 입력된 순서에 맞게 존재해야된다.
{ "foo":"I just said hello world" }
{ "foo":"Hello world" }
{ "foo":"World Hello" }
{
"query": {
"match_phrase": {
"foo": "Hello World"
}
}
}
//1번째 2번째만 리턴된다. 3번째는 순서가 틀림
6. match_boolean_prefix
마지막 term을 제외한 모든 term은 term query에 사용된다. 마지막 term은 prefix query에 사용된다.
따라서 아래의 match_bool_prefix는 그 밑의 term과 prefix로 이루어진 query와 동일하다
GET /_search
{
"query": {
"match_bool_prefix" : {
"message" : "quick brown f"
}
}
}
GET /_search
{
"query": {
"bool" : {
"should": [
{ "term": { "message": "quick" }},
{ "term": { "message": "brown" }},
{ "prefix": { "message": "f"}}
]
}
}
}
match_phrase_prefix와 상당히 유사하지만 match_phrase_prefix는 입력값을 phrase로 보고 쭉 이어진 하나로 검색을 하는 반면, match_boolean_prefix는 term단위로 검색을 하기때문에 서로 떨어져 있어도 가능하고, 순서가 뒤섞여있어도 가능하다.
7. match_phrase_prefix
위에서 언급했던 것처럼 입력값을 하나의 뭉텅이로 검색한다 따라서:
- quick brown fox (O)
- two quick brown ferrets (O)
- the fox is quick and brown (X)
8. multi_match
multi_match는 multi query를 바탕으로 여러 field를 동시에 쿼리할 수 있도록 한다.
GET /_search
{
"query": {
"multi_match" : {
"query" : "this is a test",
"fields" : [ "subject^3", "*_name" ]
}
}
}
위의 코드처럼 subject 필드에 3배의 가중치를 줄 수 있으며 field이름에 * wildcard를 사용할 수 있다.
만약 field가 명시되어 있지 않다면 index.query.default_field로 설정된 field에서 검색하고, 이 default_field는 따로 명시하지 않았다면, index의 field는 term query를 수행할 수 있는 모든 field를 추출하여 수행한다.
multi_match가 어떻게 작동할지는 type 파라미터에 따라 결정된다.
- best_fields: 여러개의 field들 중에서 입력값 단어들 중 가장 많은 단어를 가지고 있는 하나의 field의 점수를 사용
- most_fields: 여러개의 field들의 점수를 산출한뒤 합산하고 field의 개수로 나눈 평균점수를 사용한다
- phrase / phrase_prefix: best_fields와 똑같지만 match_phrase / match_phrase_prefix를 match대신 사용
- cross fields: 여러개의 field가 동시에 만족되야할 경우(예: 성과 이름이 다른 field에 들어가있을때). query string을 individual term으로 analyze한 뒤에 마치 하나의 field를 검색하는 것처럼 모든 field를 살펴본다.
(위의 best_field와 most_field와는 달리 어느 하나의 field에 모든 term이 존재하면 된다)
(주의: cross_fields에는 fuzziness가 사용될 수 없다)
tie_breaker: 점수가 산정되는 방식을 결정한다:
- 0.0 : 모든 field 중 가장 높은 점수를 가진 field의 점수를 선택
- 1.0 : 모든 field의 점수를 합함
- 0.0 < n < 1.0: 가장 높은 field의 점수 + (n * 나머지 matching field 점수)
댓글
댓글 쓰기