анализатор с токеном ngram в зависимости от длины термина - PullRequest
1 голос
/ 10 июня 2019

Я строю анализатор для частичного поиска по термину. Поэтому я хочу использовать 2-5 нграмм токенцера во время индекса и 5-5 нграм при поиске.

Рациональное использование 2-5 нграмм во время индекса состоит в том, что частичный запрос длины 2 должен совпадать.

При поиске, если поисковый термин имеет длину меньше 5, этот термин можно искать непосредственно в инвертированном индексе. Если его длина больше 5, то термин помечается 5 граммами и совпадает, если все токены совпадают.

Однако в Elastic использование 5-5 ngram tokenziser не создаст никакого токена, если длина запроса меньше 5. Решением может быть использование при поиске токенайзера 2-5, так же как и для индексации, но это приведет к поиску всех токенов 2gram, 3grams и 4grams, что бесполезно ... (достаточно токена 5grams)

Вот мое текущее отображение индекса:

{
  "settings" : {
   "analysis":{
        "analyzer":{
           "index_partial":{
              "type":"custom",
              "tokenizer":"2-5_ngram_token"
           },
           "search_partial":{
              "type":"custom",
              "tokenizer": "5-5_ngram_token"
           }
        },
        "tokenizer":{
           "2-5_ngram_token": {
              "type":"nGram",
              "min_gram":"2",
              "max_gram":"5"
           },
           "5-5_ngram_token": {
              "type":"nGram",
              "min_gram":"5",
              "max_gram":"5"
           }
        }
      }
   },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "name_trans": {
        "type": "text",
        "fields": {
          "partial": {
           "type":"text",
           "analyzer":"index_partial",
           "search_analyzer":"search_partial"
          }
        }
      }
    }
  }
}

Итак, мой вопрос: как можно создать анализатор, который не будет работать, если поисковый запрос имеет длину меньше 5. Если он имеет длину больше 5, он создает токены на 5 грамм?

---------------------- ОБНОВЛЕНИЕ С РАБОТОЙ ВОКРУГ РЕШЕНИЯ -------------------- ---

Кажется невозможным создать анализатор, который не работает, если len <5 и 5-5ngram, если len> = 5.

Существует два варианта решения для частичного выполнения:

1- Как упомянул @Amit Khandelwal, одним из решений является использование максограмм во время индекса. Если в вашем поле максимум 30 символов, используйте токенайзер с ngram 2-30 и во время поиска ищите точный термин, не обрабатывая его с помощью анализатора ngram (либо через запрос термина, либо задав для анализатора поиска ключевое слово).

Недостатком этого решения является то, что оно может привести к огромному инвертированному индексу в зависимости от максимальной длины.

2- Другое решение - создать два поля: - один для краткого поискового запроса, который можно искать в инвертированном индексе напрямую, без использования токенов - один для более длинного поискового запроса, который должен быть токенизирован В зависимости от длины термина поискового запроса поиск должен выполняться по любому из этих двух полей

Ниже приведено сопоставление, которое я использовал для решения 2 (предел между краткосрочной и долгосрочной перспективой, который я выбрал, составляет len = 5):

PUT name_test
{
  "settings" : {
   "max_ngram_diff": 3,
   "analysis":{
        "analyzer":{
           "2-4nGrams":{
              "type":"custom",
              "tokenizer":"2-4_ngram_token",
              "filter": ["lowercase"]
           },
           "5-5nGrams":{
              "type":"custom",
              "tokenizer": "5-5_ngram_token",
              "filter": ["lowercase"]
           }
        },
        "tokenizer":{
           "2-4_ngram_token": {
              "type":"nGram",
              "min_gram":"2",
              "max_gram":"4"
           },
           "5-5_ngram_token": {
              "type":"nGram",
              "min_gram":"5",
              "max_gram":"5"
           }
        }
      }
   },
  "mappings": {
    "properties": {
      "name": {
        "type": "keyword"
      },
      "name_trans": {
        "type": "text",
        "fields": {
          "2-4partial": {
           "type":"text",
           "analyzer":"2-4nGrams",
           "search_analyzer":"keyword"
          },
          "5-5partial": {
           "type":"text",
           "analyzer":"5-5nGrams"
          }
        }
      }
    }
  }
}

и два вида запросов, которые будут использоваться с этим отображением в зависимости от длины поискового запроса:

GET name_test/_search
{
  "query": {
    "match": {
      "name_trans.2-4partial": {
        "query": "ema",
        "operator": "and",
        "fuzziness": 0
      }
    }
  }
}

GET name_test/_search
{
  "query": {
    "match": {
      "name_trans.5-5partial": {
        "query": "emanue",
        "operator": "and",
        "fuzziness": 0
      }
    }
  }

Может быть, это кому-нибудь когда-нибудь поможет:)

1 Ответ

1 голос
/ 10 июня 2019

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

  1. Создайте пользовательский анализатор, используя 2-5 ngram tokenzier для полей, которые вы хотите использовать для частичного поиска, при этом будут храниться маркеры ngram полей в инвертированном индексе, например, для поля, содержащего foobar в качестве значения он будет хранить fo, foo, foob, fooba, oo, oob, ooba, oobar, ob, oba, obar , ba, bar, ar.

  2. Теперь вместо запроса на совпадение используйте термин запрос к частичным полям, который не анализируется, вы можете прочитать diff ч / б эти здесь .

  3. Так что теперь, в данном случае, не имеет значения, будет ли поисковый термин меньше 5 или нет, он все равно будет соответствовать токенам, и вы получите результаты.

Теперь давайте пробуем запустить это поле для поля, содержащего foobar в качестве значения, и протестируем его по некоторым поисковым терминам,

Случай 1: если поисковый термин содержит менее 5 символов, таких как fo, oo, ar, bar, oob, oba, bar и ooba, он все равно будет совпадают, так как эти токены присутствуют в инвертированном индексе.

Случай 2: поисковый термин содержит равные или более 5 символов, например fooba, oobar, затем также возвращает документ, так как индекс содержит эти токены.

Дайте мне знать, если это ясно или вам нужны дополнительные разъяснения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...