elasticsearch ngrams: почему сопоставляется более короткий токен, а не более длинный?

У меня есть индекс со следующим сопоставлением и анализатором:

settings: {
    analysis: {
      char_filter: {
        custom_cleaner: {
          # remove - and * (we don't want them here)
          type: "mapping",
          mappings: ["-=>", "*=>"]
        }
      },
      analyzer: {
        custom_ngram: {
          tokenizer: "standard",
          filter: [ "lowercase", "custom_ngram_filter" ],
          char_filter: ["custom_cleaner"]
        }
      },
      filter: {
        custom_ngram_filter: {
          type: "nGram",
          min_gram: 3,
          max_gram: 20,
          token_chars: [ "letter", "digit" ]
        }
      }
    }
  },
  mappings: {
    attributes: {
      properties: {
        name: { type: "string"},
        words: { type: "string", similarity: "BM25", analyzer: "custom_ngram" }
      }
    }
  }
}

И у меня есть следующие 2 документа в индексе:

"name": "shirts", "words": [ "shirt"]

и

"name": "t-shirts", "words": ["t-shirt"]

Я выполняю запрос с несколькими совпадениями как

"query": {

            "multi_match": {
               "query": "t-shirt",
               "fields": [
                  "words",
                  "name"
               ],
               "analyzer": "custom_ngram"
            }

   }

Вопрос:

У рубашек – 1,17, а у футболки – 0,8. Почему это так и как я могу добиться того, чтобы футболка (прямое соответствие) имела более высокий балл?

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

Благодарю вас!


person udo    schedule 26.03.2014    source источник


Ответы (1)


Я считаю, что это происходит, потому что вы используете StandardTokenizer, который разбивает строку «t-shirt» на токены «t» и «shirt». «t», однако, короче минимального размера грамма, поэтому токены из него не генерируются. Таким образом, вы получаете одинаковые совпадения в каждом случае, но документ с t-shirt длиннее и поэтому оценивается немного ниже.

Вы можете получить подробную информацию о том, почему документы получают такие оценки, используя ссылку Объяснить API.

Вы уверены, что вам нужно использовать ngrams? Ваш пример, «рубашка» в «мышечной рубашке» должен прекрасно обрабатываться StandardAnalyzer, который будет обозначаться дефисом.

person femtoRgon    schedule 26.03.2014
comment
Спасибо за ответ! Я попробую через минуту. Я думаю, мне нужны ngrams, так как я хочу, чтобы они соответствовали и Muscleshirt. Можно ли это сделать без ngrams? (на самом деле, это должно совпадать с Muscle-shirt и Muscleshirt [извините за неправильный пример]) - person udo; 26.03.2014
comment
объясните мне, вы абсолютно правы. разве char_filter не должен вырезать - из футболки? когда я анализирую футболку, elasticsearch возвращает ngrams без - (tsh, shi, hir, irt, ...) - person udo; 27.03.2014
comment
Хм. Вы правы, это не совсем разумно. Можете ли вы опубликовать вывод объяснения? - person femtoRgon; 27.03.2014
comment
Оказывается, я забыл инициализировать индекс с этими настройками, поэтому он использовал настройки по умолчанию... о боже... спасибо за вашу поддержку! - person udo; 28.03.2014