Как сделать точное совпадение фраз в упругом поиске? - PullRequest
0 голосов
/ 06 сентября 2018

Я пытаюсь реализовать точный поиск совпадений в упругом поиске. Но я не получаю требуемых результатов. Вот код, объясняющий проблему, с которой я столкнулся, и вещи, которые я попробовал.

doc1 = {"sentence": "Today is a sunny day."}
doc2 = {"sentence": " Today is a sunny day but tomorrow it might rain"}
doc3 = {"sentence": "I know I am awesome"}
doc4 = {"sentence": "The taste of your dish is awesome"}
doc5 = {"sentence": "The taste of banana shake is good"}

# Indexing the above docs

es.index(index="english",doc_type="sentences",id=1,body=doc1)

es.index(index="english",doc_type="sentences",id=2,body=doc2)

es.index(index="english",doc_type="sentences",id=3,body=doc3)

es.index(index="english",doc_type="sentences",id=4,body=doc4)

es.index(index="english",doc_type="sentences",id=5,body=doc5)

запрос 1

res = es.search(index="english",body={"from":0,"size":5,
                                  "query":
                                      {"match_phrase":
                                          {"sentence":{"query":"Today is a sunny day"}
                                          }},

                                          "explain":False})

запрос 2

 res = es.search(index="english",body={"from":0,"size":5,
                                  "query":{
                                    "bool":{
                                            "must":{
                                            "match_phrase":
                                          {"sentence":{"query":"Today is a sunny day"}
                                          }},
                                            "filter":{
                                                    "term":{
                                                            "sentence.word_count": 5}},

                                          }
                                            }
                                            })

Поэтому, когда я запускаю запрос 1, я получаю doc2 в качестве верхнего результата, а я хочу, чтобы doc1 был лучшим результатом.

Когда я пытаюсь использовать фильтр для того же (чтобы ограничить длину поиска до длины запроса), как в запросе 2, я не получаю никакого результата.

Буду очень признателен, если смогу помочь с решением этой проблемы. Я хочу точное совпадение для данного запроса, а не совпадение, содержащее этот запрос.

Спасибо

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

Попробуйте использовать запрос bool

    PUT test_index/doc/1
    {"sentence": "Today is a sunny day"}

    PUT test_index/doc/2
    {"sentence": "Today is a sunny day but tomorrow it might rain"}

 -#terms query for exact match with keyword and multi match - phrase for other matches
    GET test_index/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "terms": {
                "sentence.keyword": [
                  "Today is a sunny day"
                ]
              }
            },
            {  
              "multi_match":{  
                "query":"Today is a sunny day",
                "type":"phrase",
                "fields":[  
                    "sentence"
                ]
              }
            }
          ]
        }
      }
    }

В другом варианте используется многократное совпадение для совпадения ключевых слов в качестве первого и повышения 5 и других совпадений без повышения:

PUT test_index/doc/1
{"sentence": "Today is a sunny day"}

PUT test_index/doc/2
{"sentence": "Today is a sunny day but tomorrow it might rain"}


GET test_index/_search
{  
  "query":{  
    "bool":{  
      "should":[  
        {  
          "multi_match":{  
            "query":"Today is a sunny day",
            "type":"phrase",
            "fields":[  
              "sentence.keyword"
            ],
            "boost":5
          }
        },
        {  
          "multi_match":{  
            "query":"Today is a sunny day",
            "type":"phrase",
            "fields":[  
                "sentence"
            ]
          }
        }
      ]
    }
  }
}
0 голосов
/ 21 сентября 2018

Мои смелости говорят мне, что в вашем индексе есть 5 основных сегментов, и у вас недостаточно документов, чтобы результаты были релевантными. Если вы создадите индекс с одним основным сегментом, ваш первый запрос вернет ожидаемый вами документ. Вы можете узнать больше о причине, почему это происходит в следующей статье: https://www.elastic.co/blog/practical-bm25-part-1-how-shards-affect-relevance-scoring-in-elasticsearch

Один из способов добиться того, чего вы хотите, - это использовать тип keyword, но с normalizer для строчных данных, чтобы легче было искать точные совпадения без учета регистра.

Создайте свой индекс так:

PUT english
{
  "settings": {
    "analysis": {
      "normalizer": {
        "lc_normalizer": {
          "type": "custom",
          "filter": ["lowercase"]
        }
      }
    }
  },
  "mappings": {
    "sentences": {
      "properties": {
        "sentence": {
          "type": "text",
          "fields": {
            "exact": {
              "type": "keyword",
              "normalizer": "lc_normalizer"
            }
          }
        }
      }
    }
  }
}

Затем вы можете индексировать документы как обычно.

PUT english/sentences/1
{"sentence": "Today is a sunny day"}
PUT english/sentences/2
{"sentence": "Today is a sunny day but tomorrow it might rain"}
...

Наконец, вы можете найти точное совпадение фразы, запрос ниже вернет только doc1

POST english/_search
{
  "query": {
    "match": {
      "sentence.exact": "today is a sunny day"
    }
  }
}
0 голосов
/ 07 сентября 2018

Этот запрос будет работать -

{
    "query":{
        "match_phrase":{
            "sentence":{
                "query":"Today is a sunny day"
            }
        }
    },
    "size":5,
    "from":0,
    "explain":false
}
...