ElasticSearch DSL - match, match_phrase(풀 텍스트 쿼리)

Munang·2021년 7월 13일
1

ElasticSearch

목록 보기
7/12

DSL쿼리를 공부해본다! 앞 쪽 부분이어서 aggregation들어가기 전에는 난이도가 비교적 쉽다.

앞서, DSL이 어떤 약자인지 궁금해서 검색해봤다.
DSL = Domain Specific Language 이다.
이런 약어는 무조건 풀어서 알아두는게 좋다고 생각한다.
그래야 기억에 오래 남는다.

본 포스팅에서는 match 관련 쿼리를 사용해 본다.

Search 관련 DSL

요청 url은 모두 GET http://localhost:9200/bank/_search
로 동일하다.

1. match_all

해당 인덱스의 모든 쿼리를 리턴해준다.

{
  "query":{
    "match_all":{ }
  }
}

2. match

가장 일반적인 쿼리문, 뜻 그대로 매치되냐 ? 이다.
match 속성을 쿼리 속성 안에 기재 후, 원하는 내용이 들어갈 필드와 원하는 내용을 아래와 같이 기재한다.

1. 단어 1개

나는 city 필드가 Brogan 인 데이터를 찾고싶었다.

{
  "query": {
    "match": {
      "city": "Brogan"
    }
  }
}

결과는 다음과 같다.

{
    "took": 1992,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 6.5059485,
        "hits": [
            {
                "_index": "bank",
                "_type": "account",
                "_id": "1",
                "_score": 6.5059485,
                "_source": {
                    "account_number": 1,
                    "balance": 39225,
                    "firstname": "Amber",
                    "lastname": "Duke",
                    "age": 32,
                    "gender": "M",
                    "address": "880 Holmes Lane",
                    "employer": "Pyrami",
                    "email": "amberduke@pyrami.com",
                    "city": "Brogan",
                    "state": "IL"
                }
            }
        ]
    }
}

2. 단어 2개

단어 2개 이상일 경우에는 조건이 있다.
기본적으로 or 로 검색하게 된다. 둘중에 하나라도 일치하게 되면 추출된다.

두개 모두 일치하면 score가 높은 점수로 추출되고,
두개 중 하나만 일치하면 score가 낮은 점수로 추출된다.

  • or옵션으로 검색하기
{
  "query": {
    "match": {
      "address": "Crystal Street"
    }
  }
}
  • 결과는 Street 이 있거나, Crystal이 있거나 둘중 하나라도 포함되면 추출된다. (일부만 추출해서 보여준다.)
{
    "took": 1570,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 385,
            "relation": "eq"
        },
        "max_score": 7.455468,
        "hits": [
            {
                "_index": "bank",
                "_type": "account",
                "_id": "964",
                "_score": 7.455468,
                "_source": {
                    "account_number": 964,
                    "balance": 26154,
                    "firstname": "Elena",
                    "lastname": "Waller",
                    "age": 34,
                    "gender": "F",
                    "address": "618 Crystal Street",
                    "employer": "Insurety",
                    "email": "elenawaller@insurety.com",
                    "city": "Gallina",
                    "state": "NY"
                }
            },
            {
                "_index": "bank",
                "_type": "account",
                "_id": "6",
                "_score": 0.95395315,
                "_source": {
                    "account_number": 6,
                    "balance": 5686,
                    "firstname": "Hattie",
                    "lastname": "Bond",
                    "age": 36,
                    "gender": "M",
                    "address": "671 Bristol Street",
                    "employer": "Netagy",
                    "email": "hattiebond@netagy.com",
                    "city": "Dante",
                    "state": "TN"
                }
            },
            {
                "_index": "bank",
                "_type": "account",
                "_id": "13",
                "_score": 0.95395315,
                "_source": {
                    "account_number": 13,
                    "balance": 32838,
                    "firstname": "Nanette",
                    "lastname": "Bates",
                    "age": 28,
                    "gender": "F",
                    "address": "789 Madison Street",
                    "employer": "Quility",
                    "email": "nanettebates@quility.com",
                    "city": "Nogal",
                    "state": "VA"
                }
            },
            {
                "_index": "bank",
                "_type": "account",
                "_id": "32",
                "_score": 0.95395315,
                "_source": {
                    "account_number": 32,
                    "balance": 48086,
                    "firstname": "Dillard",
                    "lastname": "Mcpherson",
                    "age": 34,
                    "gender": "F",
                    "address": "702 Quentin Street",
                    "employer": "Quailcom",
                    "email": "dillardmcpherson@quailcom.com",
                    "city": "Veguita",
                    "state": "IN"
                }
            }
        ]
    }
}
  • and 옵션으로 검색하기
{
  "query": {
    "match": {
      "address": {
        "query": "Crystal Street",
        "operator": "and"
      }
    }
  }
}

결과는 다음과 같다.

{
    "took": 535,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 7.455468,
        "hits": [
            {
                "_index": "bank",
                "_type": "account",
                "_id": "964",
                "_score": 7.455468,
                "_source": {
                    "account_number": 964,
                    "balance": 26154,
                    "firstname": "Elena",
                    "lastname": "Waller",
                    "age": 34,
                    "gender": "F",
                    "address": "618 Crystal Street",
                    "employer": "Insurety",
                    "email": "elenawaller@insurety.com",
                    "city": "Gallina",
                    "state": "NY"
                }
            }
        ]
    }
}

근데 여기서 주의해야 할 점이 있다.
지금은 주소가 붙어서 나와있지만, 실제로는
Crystal Test Address 이런 주소여도 매칭되어 나오게 된다.
즉, 토큰단위로 true/false를 검색한다고 생각하면 된다.

3. match_phrase

앞선 문제점을 해결하기 위해 나온 쿼리 옵션이다.
말 그대로 Crystal Address 자체를 찾는 것이다. 나는 현업에서 로그 데이터를 필터링 하기 위해 매치 프레이스를 많이 썼던 것으로 기억한다. 쿼리스트링도 많이 쓰지만, 매치 프레이스가 그냥 깔끔하고 간단하고 쉽다....

match_phrase 예시를 사용하기 위해서 이 홈페이지에 나와있는 샘플 데이터를 사용했다.

그리고, lazy dog를 검색했다.

{
  "query": {
    "match_phrase": {
      "message": "lazy dog"
    }
  }
}

결과는 다음과 같다.

  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9489645,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.9489645,
        "_source" : {
          "message" : "The quick brown fox jumps over the lazy dog"
        }
      }
    ]
  }
}

+) 추가로, slop옵션을 사용해서 lazy dog 사이에 n개 이상의 단어를 허용할 수 있다.

{
  "query": {
    "match_phrase": {
      "message": {
        "query": "lazy dog",
        "slop": 1
      }
    }
  }
}

결과는 다음과 같다.

{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0110221,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0110221,
        "_source" : {
          "message" : "Lazy jumping dog"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.9489645,
        "_source" : {
          "message" : "The quick brown fox jumps over the lazy dog"
        }
      }
    ]
  }
}

다음은 bool쿼리를 알아보도록 하자.

0개의 댓글