Норма поля ElasticSearch всегда равна 1

#elasticsearch

#elasticsearch

Вопрос:

Я недавно начал работать с elasticsearch, поэтому прошу прощения, если это «базовый» вопрос. Я также находился в процессе переноса наших материалов с ES версии 1.3 на 2.4 (!), Поэтому в процессе некоторые вещи сломались, и запросы / etc., которые раньше работали, больше не работают (или дают «плохие» результаты). Я исправил некоторые из этих проблем, но это тупик.

Я прочитал документы о том, как выполняется оценка релевантности. Мой индекс обрабатывается с помощью маркера шаблона (просто разбивается на слова), затем используется фильтр нижнего регистра и фильтр ngram (минимальная длина 1, максимальная длина 3).

Теперь, если я буду искать букву «a», тогда я должен сначала получить относительно более короткие документы, верно? Так, например, «asian» (который содержит два экземпляра желаемого токена) должен иметь более высокий балл, чем «Astasia-abasia» (у которого шесть), потому что пропорционально больше его токенов равно «a». Пропорциональность учитывается частотой термина и нормой поля. Отлично! Это то, что я хочу. Но …

На самом деле «азиатский» даже не появляется в первых 5000 обращениях! Когда я смотрю ?explain , я вижу, что пока fieldNorm присутствует, но всегда равно 1. Почему это так? Как я могу это исправить?

Код индекса, который я использую, находится здесь:

 {
    "settings": {
        "number_of_shards": 1,
        "number_of_replicas": 0,
        "analysis": {
            "analyzer": {
                "ngram_analyzer": {
                    "tokenizer": "pattern_tokenizer",
                    "filter": [ "lowercase", "ngram_filter" ]
                }
            },
            "tokenizer": {
                "pattern_tokenizer": {
                    "type": "pattern",
                    "pattern": "[\]\[{}()/ ,:;"amp;] "
                }
            },
            "filter": {
                "ngram_filter": {
                    "type": "ngram",
                    "min_gram": "1",
                    "max_gram": "3"
                }
            }
        }
    },
    "mappings": {
        "terms": {
            "properties": {
                "code": {
                    "analyzer": "ngram_analyzer",
                    "search_analyzer": "keyword",
                    "type": "string",
                    "norms": {
                        "enabled": true,
                        "loading": "eager"
                    }
                },
                "codeAbbr": {
                    "analyzer": "ngram_analyzer",
                    "search_analyzer": "keyword",
                    "type": "string",
                    "norms": {
                        "enabled": true,
                        "loading": "eager"
                    }
                },
                "term": {
                    "analyzer": "ngram_analyzer",
                    "search_analyzer": "keyword",
                    "type": "string",
                    "norms": {
                        "enabled": true,
                        "loading": "eager"
                    }
                }
            }
        }
    }
}
  

Я не чувствую, что мне даже нужно указывать атрибут norms (я чувствую, что указанное выше должно быть по умолчанию), но это не имеет значения. Если я выну их или вставлю, ответ будет тот же. Как я могу заставить fieldNorm работать правильно?

Комментарии:

1. Можете ли вы поделиться своим запросом? И результаты вашего объяснения? Также можете ли вы проверить, сколько терминов присутствует в одном из полей? Вы можете выполнить агрегацию терминов в поле и проверить значение «sum_other_doc_count» elastic.co/guide/en/elasticsearch/reference/current /…

2. @jay спасибо за ответ, но, к сожалению, я не получил его, пока не вернулся домой с работы, и не смогу получить точный запрос и результат в субботу. Тем не менее, я считаю, что соответствующая информация содержится в приведенном выше вопросе. Запрос представляет собой запрос соответствия с одним термином «a»

3. Итак, причина, по которой я просил указать количество терминов — fieldNorm рассчитывается как 1 / squareroot (количество терминов). Что означает, что чем больше число терминов, тем меньше fieldNorm. Все ваши поля используют ngrams, что означает, что количество терминов будет v v высоким. Значение 1, которое вы видите — из того, что я читал, значение является увеличением времени индекса по умолчанию на 1 норма поля. Значение хранится в одном байте, поэтому точность теряется.

Ответ №1:

Ответ оказался несколько иным, чем я ожидал; Я надеюсь, что этот ответ поможет кому-то еще сэкономить время, которое я потратил. Я не видел этого нигде в документах, которые я читал, но обнаружил это с помощью экспериментов. Моя очень специфическая проблема может быть решена с помощью токенизатора ngram, а не фильтра ngram, но позвольте мне объяснить, почему это так.

Проблема заключается в том, когда вычисляется fieldNorm, и это одна из причин, почему фильтры ngram и токенизаторы отличаются.

fieldNorm основано на количестве токенов в документе, используя формулу, указанную в документах 1/sqrt(#tokens) ; в знаменателе может быть или не быть 1, в зависимости от того, кого вы спрашиваете, но это не имеет большого значения для этого вопроса. Важно то, что #tokens цифра вычисляется после токенизации, но перед фильтрацией.

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

  1. Предположим, ваши документы состоят из длинных фраз — может быть, описаний? — и вы маркируете с помощью стандартного токенизатора или чего-то еще. Тогда ваша норма поля основана в основном на количестве слов. Это может быть то, что вы хотите; это зависит от вашего варианта использования. Таким образом, поиск предпочитает более короткие документы с точки зрения количества слов (но использование длинных слов не наказывает ваш поиск). Если вместо этого вы используете токенизатор ngram, норма поля пропорциональна количеству символов; поэтому, если вы используете много маленьких слов, а я использую меньше, но больше слов, наши оценки могут быть одинаковыми. Обычно это не то, что вы хотите.

  2. Теперь предположим, что ваши документы состоят из отдельных слов или очень коротких фраз (как у меня). Если вы выполняете токенизацию с помощью стандартного токенизатора, большинство документов будут иметь fieldNorm 1, поскольку они представляют собой отдельные слова. Однако я хочу, чтобы в моем поиске приоритет отдавался более коротким словам (в качестве приближения к «общим словам»), так что это не помогает. Вместо этого я буду использовать токенизатор ngram, поэтому более длинные слова будут помещены на дно, а более короткие слова всплывут наверх.