Функция автозаполнения анализатора ElasticSearch для буквенно-цифровой - PullRequest
1 голос
/ 01 апреля 2020

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

  1. Пользователь может искать полный код alphanumeri c или только целую часть.
    Пример : для 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. Будет ли это отображение, как я смогу достичь вышеупомянутого Функция автозаполнения .

1 Ответ

0 голосов
/ 01 апреля 2020

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

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

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

Индекс Def

{
    "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, должен содержать 2 документа в примерах данных 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"
        }
      }
    ]
...