Функция автозаполнения анализатора ElasticSearch для буквенно-цифровых

У меня есть буквенно-цифровые коды, такие как Hcc18, HCC23, I23, которые я хочу сохранить в ElasticSearch. Над этим я хочу построить следующие две функции: -

  1. Пользователь может искать полный буквенно-цифровой код или только целую часть.
    Пример: для hcc15 или 15 hcc15 должен быть в выходных данных и в верхней части результатов.
  2. Функция автозаполнения: когда пользователь вводит, скажем, I42, результаты должны содержать I420, I421 и т. д.

Мое текущее сопоставление Elasticsearch:

"mappings": {
  "properties": {
    "code": {
      "type": "text",
      "analyzer": "autoanalyer"
    }
  }
},
"settings": {
  "analysis": {
    "analyzer": {
      "autoanalyer": {
        "tokenizer": "standard",
        "filter": [
          "lowercase",
        ]
      }
    },
    "tokenizer": {
      "autotoken": {
        "type": "simple_pattern",
        "pattern": "[0-9]+"
      }
    }
  }
}

Делается запрос:

{
    "min_score": 0.1,
    "from": 0,
    "size": 10000,
    "query": {
        "bool": {
            "should": [{ "match": {"code": search_term}}]
        }
    }
}

Две проблемы, с которыми я сталкиваюсь при таком подходе: -

  1. Допустим, я ищу I420, теперь, поскольку сопоставление основано только на цифрах, я получаю все коды, относящиеся к числу 420, но точное совпадение I420 не приходит на вершине.

  2. Будет ли это сопоставление, как я смогу реализовать вышеупомянутую функцию автозаполнения.


person Abhimanyu    schedule 01.04.2020    source источник
comment
Отличный вопрос, было бы лучше, если бы вы могли разделить его на 2 части, так что есть несколько требований, которые я только что сделал, составив свой ответ и протестировав его с вашими данными, пожалуйста, посмотрите и не стесняйтесь комментировать, если вам нужно больше информации.   -  person user156327    schedule 01.04.2020
comment
@OpsterElasticsearchNinja Я согласился, что мне нужно было разбить его на две части. Также ваш ответ решает большую часть проблемы.   -  person Abhimanyu    schedule 02.04.2020
comment
@OpsterElasticsearchNinja, однако, это не решает одну из моих проблем. Допустим, у меня есть сохраненные коды типа E1151, E1152. Когда я запрашиваю E115, я получаю такие результаты, как E1151, E1151, E1153, что именно то, что я хочу. Но тогда ищу 115 вместо Е115 результата нет. Поэтому для меня не имеет значения, набирает ли пользователь E115 или просто 115. Функция автозаполнения должна работать и с числами.   -  person Abhimanyu    schedule 02.04.2020


Ответы (1)


У вас было несколько требований, и все они могут быть достигнуты с помощью

  1. Создание специального анализатора, который токенизирует данные в соответствии с нашими требованиями.
  2. Использование логического запроса с комбинацией префикс (для автозаполнения) и совпадение для поиска по номеру.

Ниже приведен пошаговый пример с использованием данных и запросов OP.

Индекс определения

{
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "autotoken" -->used your analyzer to extract numbers
                }
            },
            "tokenizer": {
                "autotoken": {
                    "type": "simple_pattern",
                    "pattern": "[0-9]+",
                    "preserve_original": true
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "code": {
                "type": "keyword",
                "fields": {
                    "number": {
                        "type": "text",
                        "analyzer" : "my_analyzer"
                    }
                }
            }
        }
    }
}

Индексировать несколько документов

{
  "code" : "hcc420"
}

{
  "code" : "HCC23"
}

{
  "code" : "I23"
}

{
  "code" : "I420"
}

{
  "code" : "I421"
}

{
  "code" : "hcc420"
}

Поисковый запрос (проблема 1, поиск I420, должен привести к двум документам в выборке данных I420 и hcc420, но I420 должен иметь больше баллов как точное совпадение)

{
    "query": {
        "bool": {
            "should": [
                {
                    "prefix": {
                        "code": {
                            "value": "I420"
                        }
                    }
                },
                {
                    "match": {
                        "code.number": "I420"
                    }
                }
            ]
        }
    }
}

Результат

"hits": [
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "4",
        "_score": 2.0296195, --> note exact match having high score
        "_source": {
          "code": "I420"
        }
      },
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "7",
        "_score": 1.0296195,
        "_source": {
          "code": "hcc420"
        }
      }
    ]

Часть 2. Тот же поисковый запрос можно использовать с функцией автозаполнения

Таким образом, поиск I42 должен привести к I420 и I421 из примеров документов.

{
    "query": {
        "bool": {
            "should": [
                {
                    "prefix": {
                        "code": {
                            "value": "I42"
                        }
                    }
                },
                {
                    "match": {
                        "code.number": "I42"
                    }
                }
            ]
        }
    }
}

Результат

 "hits": [
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "4",
        "_score": 1.0,
        "_source": {
          "code": "I420"
        }
      },
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "5",
        "_score": 1.0,
        "_source": {
          "code": "I421"
        }
      }
    ]

Давайте возьмем другой пример для поиска по номеру, поиск 420 должен привести к hcc420 и I420.

Поисковый запрос

 {
        "query": {
            "bool": {
                "should": [
                    {
                        "prefix": {
                            "code": {
                                "value": "420"
                            }
                        }
                    },
                    {
                        "match": {
                            "code.number": "420"
                        }
                    }
                ]
            }
        }
    }

And whoa, again it gave expected results ????

Result
------


 "hits": [
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "4",
        "_score": 1.0296195,
        "_source": {
          "code": "I420"
        }
      },
      {
        "_index": "so_number",
        "_type": "_doc",
        "_id": "7",
        "_score": 1.0296195,
        "_source": {
          "code": "hcc420"
        }
      }
    ]
person user156327    schedule 01.04.2020
comment
Спасибо @Opster, это сработало очень хорошо. Несколько вещей не работали, как когда я запрашивал I42 . тогда такие коды, как I420, I421, не появлялись наверху. Я загрузил префиксный запрос на 10, то есть `{prefix: {code: {value: search_term, boost: 10}}}`. И это сработало. еще раз спасибо! - person Abhimanyu; 02.04.2020
comment
@Abhimanyu, всегда приятно слышать, что это было полезно, могу ли я попросить вас отметить этот ответ и также проголосовать за него, я потратил на это довольно много времени и был разочарован, когда какой-то пользователь, я думаю, не понимая, проголосовал против моего ответа: | - person user156327; 02.04.2020
comment
Конечно, подойдет. Можете ли вы помочь с проблемами, которые я упомянул в комментарии выше? - person Abhimanyu; 02.04.2020
comment
Конечно, но, как обсуждалось ранее, вы можете задать для этого отдельный вопрос, так как это было бы более полезно для сообщества, и прокомментируйте мне ссылку на вопрос. и принять и проголосовать за ответ :) - person user156327; 02.04.2020
comment
@Abhimanyu, спасибо за отмеченный ответ, жду вашего нового вопроса с подробной информацией :) - person user156327; 02.04.2020