Не знаю, как сортировать результаты эластичного поиска.

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

Elasticsearch::Transport::Transport::Errors::BadRequest: [400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"profiles","node":"mad6gavaR3yTFabsF9m0rg","reason":{"type":"illegal_argument_exception","reason":"Fielddata is disabled on text fields by default. Set fielddata=true on [name] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory. Alternatively use a keyword field instead."}}]},"status":400}
from /Users/ngw/.rvm/gems/ruby-2.2.2@utelier/gems/elasticsearch-transport-5.0.4/lib/elasticsearch/transport/transport/base.rb:202:in `__raise_transport_error'

что, по-видимому, говорит мне, что способ, которым я настроил индексы, неверен. Вот что я индексирую

def as_indexed_json(options={})
  {
    profile_type:     profile_type,
    name:             name,
    specialisation:   specialisation,
    description:      description,
    tags:             tags,
    minimum_order:    minimum_order,
    company_city:     company_city,
    company_address:  company_address,
    continent_id:     country.try(:continent).try(:id),
    country_id:       country.try(:id),
    industry:         industry.try(:id)
  }
end

Запрос может использовать любое из этих полей, но не: name, которое используется только для целей сортировки. Конфигурация моего индекса очень проста:

settings index: { number_of_shards: 1 } do
  mapping dynamic: false do
    indexes :name, type: 'text'
    indexes :description, analyzer: 'english'
  end
end

Я почти уверен, что мои индексы настроены неправильно, но после поиска в течение некоторого времени в тестах по модели asticsearch я не могу найти ничего релевантного. Может кто-нибудь помочь мне понять это? Заранее спасибо.

2 ответа

Решение

Конечно, проблема в том, что тип имени - текст. Из эластичного поиска 5 вы не можете сортировать по анализируемому полю по умолчанию

Сортировка может выполняться либо по полям с включенными field_data или doc_values ​​-> структура данных, которую эластичный поиск использует для сортировки и агрегирования.

  • Значения Doc_values ​​нельзя включить в анализируемые строковые поля.
  • И field_data по умолчанию отключено для анализируемых строковых полей.

Вы можете сделать две вещи

  • либо измените отображение имени на ключевое слово->, которое будет non_analyzed, и тогда doc_values ​​будет включен для него.
  • Или вы можете включить field_data для имени поля с помощью "fielddata": true Вот ссылки, ссылающиеся на это

https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/doc-values.html

Вы можете использовать несколько полей:

На ваше indexes:

      settings index: { number_of_shards: 1 } do
  mapping dynamic: false do
    indexes :name, type: 'text', fields: { keyword: { type: :keyword } }
    indexes :description, analyzer: 'english'
  end
end

По вашему запросу:

      Model.search(
  query: ...
  sort: {
    'name.keyword':  { order: 'asc' }
  }
)

Или просто установите fielddata к true(Предупреждение: не рекомендуется, так как он использует намного больше ресурсов):

      settings index: { number_of_shards: 1 } do
  mapping dynamic: false do
    indexes :name, type: 'text', fielddata: true
    indexes :description, analyzer: 'english'
  end
end

Взгляните на эти ссылки:

Другие вопросы по тегам