Нечеткие совпадения получают более высокие баллы, чем точные совпадения

Я новичок в ElasticSearch и пытался настроить Elasticsearch для получения нечетких совпадений. При реализации нечеткого поиска, фильтра автозаполнения и черепицы точные совпадения, похоже, имеют более низкий балл, чем частичные совпадения. Например, если запрос - «Кольцо», кажется, что он больше соответствует «Медному кольцу», а не «Кольцу».

Может кто-нибудь мне помочь?

Вот как я делаю индекс:

 itemindex = es.indices.create(
        index='mo-items-index-1',
        body={
        "settings": {
            "number_of_shards": 1,
            "analysis": {
                "filter": {
                    "autocomplete_filter": {
                        "type":     "edge_ngram",
                        "min_gram": 1,
                        "max_gram": 20
                    },
                    "custom_shingle": {
                        "type": "shingle",
                        "min_shingle_size": 2,
                        "max_shingle_size": 3,
                        "output_unigrams": True

                    },
                    "my_char_filter": {
                        "type": "pattern_replace",
                        "pattern": " ",
                        "replacement": ""
                    }
                },
                "analyzer": {
                    "autocomplete": {
                        "type":      "custom",
                        "tokenizer": "standard",
                        "filter": [
                            "lowercase",
                            "custom_shingle",
                            "autocomplete_filter",
                            "my_char_filter"
                        ]
                    }
                }
            }
        },
        "mappings": {
        "my_type": {
            "properties": {
                "item_id": {
                    "type":     "string",
                    "analyzer": "autocomplete",
            "search_analyzer": "standard"

                },
            "item_name": {
                    "type":     "string",
                    "analyzer": "autocomplete",
            "search_analyzer": "standard"

                }
            }
        }
    }
       },
        # Will ignore 400 errors, remove to ensure you're prompted
       ignore=400
    )

Вот как я запрашиваю термин:

 res2 = es.search(index="mo-items-index-1", size=200, body={"query": {"multi_match": {
        "fields": [
            "item_name", "item_id"], "query": userQuery, "fuzziness": "AUTO"}}, "highlight": {

        "fields": {
            "item_name": {},
            "item_id": {}

        }
    }, })

person Abhijay    schedule 16.12.2017    source источник


Ответы (1)


Существует очень простой способ "увеличить" количество точных совпадений: использовать bool запрос, который будет использовать ваш уже существующий запрос, и term запрос внутри should операторов:

  "query": {
    "bool": {
      "should": [
        {
          "multi_match": {
            "fields": [
              "item_name",
              "item_id"
            ],
            "query": "Ring",
            "fuzziness": "AUTO"
          }
        },
        {
          "term": {
            "item_name.keyword": {
              "value": "Ring"
            }
          }
        }
      ]
    }
  }

И вам также нужно будет добавить keyword тип подполя к полю, для которого вы хотите добиться идеального соответствия:

  "mappings": {
    "my_type": {
      "properties": {
        "item_id": {
          "type": "string",
          "analyzer": "autocomplete",
          "search_analyzer": "standard"
        },
        "item_name": {
          "type": "string",
          "analyzer": "autocomplete",
          "search_analyzer": "standard",
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          }
        }
      }
    }
  }
person Andrei Stefan    schedule 18.12.2017
comment
Спасибо за ответ! У меня есть такие предметы, как булавка, значок с Микки Маусом, синяя булавка и кепка, бейсболка, красная кепка, так что мне нужно добавить булавку, кепку и т. Д. В поле значения в поле item_name.keyword? Что-то вроде значения: [Ring, Pin, Cap]? заранее спасибо - person Abhijay; 18.12.2017
comment
Судя по вашему вопросу, вы не читали документацию по Elasticsearch. Даже не основы. Для подполя вам не нужно ничего делать. Elasticsearch автоматически заполнит подполе. Если вы используете инструменты Dev в Kibana (которые я рекомендую), у вас есть полный тест с сопоставлениями, данными и запросами: gist.github.com/astefan/f3e8f9ff870c5efed860588186af7e14 - person Andrei Stefan; 18.12.2017
comment
Да, мне нужно взглянуть на документацию. С этой конфигурацией, когда я запрашиваю термин кольцо, лучшим результатом является центрирующее кольцо, когда кольцо существует в индексе. Вы можете сказать, что могло произойти? - person Abhijay; 22.12.2017
comment
Все дело в этом: elastic.co/guide /en/elasticsearch/guide/2.x/scoring-theory.html означает, сколько документов содержится в сегменте, какие термины они содержат, какова их частота, длина поля, содержащего определенный термин и т. д. По сути, чем больше документов имеет шард, тем лучше оценивается оценка. - person Andrei Stefan; 23.12.2017
comment
С этой конфигурацией, когда я запрашиваю термин кольцо, лучшим результатом является центрирующее кольцо, когда кольцо существует в индексе. Вы можете сказать, что могло произойти? Вы придумали способ убедиться, что кольцо идет до центрирующего кольца? Я застрял на той же проблеме. Ценю вашу помощь. - person Ramesh; 02.04.2018