Строка токенизации для подсказки завершения - PullRequest
0 голосов
/ 01 ноября 2018

хотите создать функцию автозаполнения веб-сайта электронной коммерции, используя Completion Suggester.

Это мой индекс:

PUT myIndex
{
    "mappings": {
        "_doc" : {
            "properties" : {
                "suggest" : {
                    "type" : "completion"
                },
                "title" : {
                    "type": "keyword"
                }, 
                "category" : { 
                    "type": "keyword"
                },
                "description" : { 
                    "type": "keyword"
                }
            }
        }
    }
}

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

POST dummy/_doc
{
  "title": "Blue asics running shoes",
  "category": "sports",
  "description": "Nice blue running shoes, size 44 eu",
  "suggest": {
    "input": "Blue Asics running shoes" // <-- use title
  }
}

Проблема в том, что упругий поиск соответствует только строке с начала ... то есть "Blu" найдет результат, но "Asic", "Run" или "Sho" ничего не вернут ...

Так что мне нужно сделать, чтобы токенизировать мой ввод следующим образом:

POST dummy/_doc
{
  "title": "Blue asics running shoes",
  "category": "sports",
  "description": "Nice blue running shoes, size 44 eu",
  "suggest": {
    "input": ["Blue", "Asics", "running", "shoes"] // <-- tokenized title
  }
}

Это бы хорошо работало ... Но как я должен токенизировать свое поле? Я знаю, что могу разбить строку в c #, но есть ли способ сделать это в Elasticsearch / Nest?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Исходя из ответа Расса Кэма выше (вариант 2), этого руководства Elasticsearch , а также этого документа , я получил следующее решение:

PUT my_index
{
  "settings": {
    "analysis": {
      "filter": {
        "edge_ngram_token_filter": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10
        },
        "additional_stop_words": {
          "type":       "stop",
          "stopwords":  ["your"]
        },
        "english_stemmer": {
          "type":       "stemmer",
          "language":   "english"
        },
        "english_possessive_stemmer": {
          "type":       "stemmer",
          "language":   "possessive_english"
        }
      },
      "char_filter": {
        "my_char_filter": {
          "type": "mapping",
          "mappings": [
            "C# => csharp",
            "c# => csharp"
          ]
        }
       },
       "analyzer": {
        "result_suggester_analyzer": { 
          "type": "custom",
          "tokenizer": "standard",
          "char_filter":  [ "html_strip", "my_char_filter" ],
          "filter": [
            "english_possessive_stemmer",
            "lowercase",
            "asciifolding",
            "stop",
            "additional_stop_words",
            "english_stemmer",
            "edge_ngram_token_filter",
            "unique"
          ]
        }
      }
    }
  }
}

Запрос для проверки этого решения:

POST my_index/_analyze
{
  "analyzer": "result_suggester_analyzer",
  "text": "C# &amp; SQL are great languages. K2 is the mountaineer's mountain. Your house-décor is à la Mode"
}

Я бы получил эти токены (NGrams):

cs, csh, csha, cshar, csharp, sq, sql, gr, gre, grea, great, la, lan, lang,
langu, langua, languag, k2, mo, mou, moun, mount, mounta, mountai, mountain, 
ho, hou, hous, hous, de, dec, deco, decor, mod, mode

Что следует отметить здесь:

  1. Я использую фильтр stop, который является английским языком по умолчанию фильтр и блокирует are, is, the - но не your.
  2. Я определил additional_stop_words, который останавливается your
  3. Я использую встроенные english & possessive_english стеммеры, которые бы токенизировали слова: 1030 * гора но не альпинизм .
  4. Я определил mapped_words_char_filter, который конвертирует C # в csharp, без этого c # не будет действительным токеном ... (этот параметр не будет токенизировать F #)
  5. Я использую встроенный html_strip, char_filter, который преобразует &amp; в &, и он игнорируется, так как наша min_gram = 2
  6. Мы используем встроенный asciifolding фильтр токенов, поэтому декор маркируется как decor .

Это код NEST для вышеуказанного:

var createIndexResponse = ElasticClient.CreateIndex(IndexName, c => c
    .Settings(st => st
        .Analysis(an => an
            .Analyzers(anz => anz
                .Custom("result_suggester_analyzer", cc => cc
                    .Tokenizer("standard")
                    .CharFilters("html_strip", "mapped_words_char_filter")
                    .Filters(new string[] { "english_possessive_stemmer", "lowercase", "asciifolding", "stop", "english_stemmer", "edge_ngram_token_filter", "unique" })
                )
            )
            .CharFilters(cf => cf
                .Mapping("mapped_words_char_filter", md => md
                    .Mappings(
                        "C# => csharp",
                        "c# => csharp"
                    )
                )
            )
            .TokenFilters(tfd => tfd
                .EdgeNGram("edge_ngram_token_filter", engd => engd
                    .MinGram(2)
                    .MaxGram(10)
                )
                .Stop("additional_stop_word", sfd => sfd.StopWords(new string[] { "your" }))
                .Stemmer("english_stemmer", esd => esd.Language("english"))
                .Stemmer("english_possessive_stemmer", epsd => epsd.Language("possessive_english"))
            )
        )
    )
    .Mappings(m => m.Map<AdDocument>(d => d.AutoMap())));
0 голосов
/ 02 ноября 2018

Указатель завершения предназначен для быстрого поиска по запросу с префиксом запросов, используя анализатор simple, а не анализатор standard, который используется по умолчанию для text типы данных.

Если вам нужно частичное совпадение префиксов на любых токенах в заголовке, а не только в начале заголовка, вы можете рассмотреть возможность использования одного из следующих подходов:

  1. используйте Анализ API с анализатором, который будет разбивать заголовок на токены / термины, из которых вы хотите частичное совпадение префикса, и индексировать эту коллекцию как input для completion поле. Стандартный анализатор может быть хорошим для начала.

    Имейте в виду, что структура данных для подсказки завершения сохраняется в памяти во время использования, поэтому высокая степень кардинальности между документами увеличит требования к памяти для этой структуры данных. Также учтите, что «оценка» соответствующих терминов проста в том смысле, что она контролируется весом, примененным к каждому входу.

или

  1. Не используйте здесь подсказку для завершения, а вместо этого установите поле title в качестве text типа данных с мультиполями , которые включают различные способы, которыми title должно быть проанализировано (или не проанализировано, например, с подполем keyword).

    Потратьте некоторое время с помощью API Analyze, чтобы создать анализатор, который позволит использовать частичный префикс терминов в любом месте заголовка. Для начала вам нужно запустить что-то вроде стандартного токенайзера, строчного фильтра токенов, фильтра токенов Edgengram и, возможно, фильтра токенов Stop. Также обратите внимание, что вам понадобится Анализатор поиска , который выполняет функции, аналогичные анализатору индекса , за исключением фильтра токенов Edgengram, так как токены во входных данных поиска не должны быть запрограммированы.

...