简体   繁体   中英

Don't know how to sort elasticsearch-model results

I'm using elasticsearch-model on my RoR application to perform a search and have the results sorted. I can perform the query and have back unsorted results, but when I add sort everything breaks with:

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'

which apparently is telling me that the way I configured the indexes is wrong. Here is what I'm indexing

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

A query can use any of these fields, but not :name, which is only used for sorting purposes. The configuration of my index is very simple:

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

I'm pretty sure my indexes are setup wrong, but after searching for some time inside elasticsearch-model tests I can't find anything relevant. Can someone help me figure this out? Thanks in advance.

Sure the problem is that the type of name is text . From elastic search 5 you can't sort on an analyzed field by default

Sorting can be either done on fields with field_data or doc_values enabled -> the data structure elasticsearch uses for sorting and aggregation.

  • Doc_values can't be enabled on analyzed string fields.
  • And field_data is by default disabled on analyzed string fields.

You can do two things

  • either change the mapping of name to keyword->which would be non_analyzed and doc_values would be enabled on it then.
  • Or you can enable field_data on field name by using "fielddata": true Here are links reffering this

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

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

You can either use multi-fields:

On your 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

On your search:

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

Or just set fielddata to true (Warning: Not recommended since it uses a lot more resources):

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

Take a look at these links:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM