Поиск по префиксу с частотным подсчетом

В тот момент, когда я индексирую текст, я сохраняю частотность каждого слова в базе данных. Это прекрасно работает, так как все поиски основаны на целых словах, и все возможные поиски известны. Но сейчас я хочу добавить возможность поиска по префиксу (поиск части слова). Я могу получить результаты/попадания из префиксного поиска с помощью elasticsearch, используя это:

GET /my_index/address/_search
{
    "query": {
        "prefix": {
            "main_text": "word_part"
        }
    }
}

см.: https://www.elastic.co/guide/en/elasticsearch/guide/current/prefix-query.html

Это мое текущее отображение:

{
    "my-index":{
        "mappings":{
            "doc":{
                "properties":{
                    "keycounter":{
                        "properties":{
                            "counter": {"type":"integer"},
                            "keyword":{"type":"keyword"}
                         }
                    },
                    "main_text":{
                        "type":"text", 
                        "fielddata":true
                    },
                    "main_text_keycounter":{
                        "properties":{
                            "counter":{
                                "type":"long"
                            },
                            "keyword":{
                                "type":"text", 
                                "fields":{
                                    "keyword":{
                                        "type":"keyword",
                                        "ignore_above":256
                                    }
                                }
                            }
                        }
                    },
                    "time_written":{
                        "type":"date"
                    },
                    "translated_text":{
                        "type":"text",
                        "fielddata":true
                    },
                }
            }
        }
    }
}

Но я не хочу подсчитывать частоту для каждого результата, который я получаю, поскольку это будет стоить O (N) для каждого текста. Есть ли какой-нибудь разумный способ хранения/получения частоты для этого типа поиска с использованием elasticsearch?


person DevB2F    schedule 31.10.2018    source источник


Ответы (2)


Вы можете использовать функцию doc-termvectors. из elasticsearch, чтобы получить статистику по терминам и количество терминов. Таким образом, вы можете сохранить свой документ, используя сопоставление, и получить статистику термина префикса при запросе. Конечно, этот подход предоставляет вам статистику терминов для каждого документа результатов, поэтому вам придется агрегировать ее для всех ваших результатов.

Вот пример сопоставления, индексированного документа и запроса doc-termvectors. Вы также можете использовать edge-ngram tokenizer для получения статистики по префиксным терминам.

Сопоставление:

PUT /my-index
{
  "mappings": {
    "doc": {
      "properties": {
        "main_text": {
          "type": "text",
          "fielddata": true,
          "term_vector": "with_positions_offsets_payloads",
          "store": true
        }
      }
    }
  }
}

Индексный документ:

POST /my-index/doc/1
{
  "main_text": "foo bar foo"
}

Получить термвекторы:

POST /my-index/doc/1/_termvectors

Результаты:

...
"terms": {
    ...
    "foo": {
      "term_freq": 2,
      "tokens": [
        {
          "position": 0,
          "start_offset": 0,
          "end_offset": 3
        },
        {
          "position": 2,
          "start_offset": 8,
          "end_offset": 11
        }
      ]
    }
    ...

Изменить

Если вы хотите получить termvectors для нескольких документов, вы можете использовать _mtermvectors конечная точка. Он предоставит вам статистику для нескольких документов. Однако он не будет учитывать частоту терминов во всех документах, что, как я понимаю, является вашим вопросом, чего вы хотите. В качестве решения вы можете сохранить результаты termvectors в эластике (тот же индекс или отдельный), а затем использовать агрегацию для подсчета общего количества терминов.

POST /my-index/doc/_mtermvectors
{
  "ids": [
    "1",
    "2"
  ],
  "parameters": {
    "fields": [
      "main_text"
    ],
    "term_statistics": true
  }
}

Изменить

Тогда я думаю, что решение состоит в том, чтобы вызывать termvectors для всех документов и сохранять результаты, то есть все частоты терминов и подтерминов, в другом индексе. Агрегируя результаты на основе ваших поисковых запросов, вы получите желаемые результаты.

person paweloque    schedule 13.11.2018
comment
Я могу получить сумму частоты для всех документов, используя последний пример из elastic.co/guide/en/elasticsearch/reference/current/ Но как получить частоту появления нескольких документов в одном запросе? - person DevB2F; 16.11.2018
comment
Я добавил некоторые идеи по этому поводу в редактировании: вы можете использовать _mtermvectors и сохранять результаты в своем эластике. После этого вы можете использовать агрегацию для подсчета общих частот. - person paweloque; 16.11.2018
comment
Спасибо, я не вижу, как фильтровать термины по тексту поиска, это дает все векторы терминов для всех текстов. - person DevB2F; 16.11.2018
comment
Можете ли вы рассказать мне больше о вашей мотивации? Для чего вам нужна эта информация? - person paweloque; 16.11.2018
comment
Пользователи должны исследовать частоту слов с течением времени, например. чтобы увидеть, как слово «автомобиль» превратилось из несуществующего в часто используемое слово в английском языке. Это исходный запрос в моем вопросе. Кажется, что фильтр для векторов терминов не позволяет использовать поисковый фильтр на основе текста, но это должно быть каким-то образом возможно - person DevB2F; 16.11.2018
comment
Будет ли вам достаточно провести статический анализ для фиксированного набора терминов? - person paweloque; 16.11.2018
comment
Фильтровать нужно как по словам, так и по частям слов. - person DevB2F; 17.11.2018

Взгляните на этот ответ, предлагающий использовать преобразователь с конечным состоянием для ускорения поиска префиксов для подсказчик завершения. Выглядит довольно аккуратно и заявлено, что эквивалентно использованию trie.

person isp-zax    schedule 13.11.2018