9
votes

I am working on elastic search multiple field sort query, I have data in the following format:

{
  "person_name" : "Abraham Benjamin deVilliers",
  "created_on": "Tue, 02 Apr 2018 16: 17: 54 GMT",
  "name": "Abraham",
  "office":{
     "name":"my_office"
  }
},
{
  "person_name" : "John Bradshaw",
  "created_on": "Thu Apr 05 2018 14:42:30 GMT",
  "name": "jhon",
  "office": {
     "name":"Abraham deVilliers"
  }
},
{
  "person_name" : "John Bradshaw",
  "created_on": "Tue, 03 Apr 2018 11: 39: 17 GMT",
  "name": "Abraham deVilliers",
  "office": {
     "name":"blabla"
  }
}

Where the field person_name is of type text and created_on is of type string. I have to sort the above response based on the fields person_name and created_on.

The query we tried is as follows:

GET /my_index/_search

{
    sort: [{ 
             "person_name": { "order": "asc" },
             "created_on": { "order": "desc" }
    }]
}

While sorting response with the above query I am getting the following error:

message: '[illegal_argument_exception] Fielddata is disabled on text fields by default. Set fielddata=true on [person_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.'

On searching, we found we need to modify the mapping of the field person_name from type text to of type keyword. But we can't modify existing mapping as it already contains millions of records.

Is there any other way to perform a sort query on the text field without altering the existing mapping of elastic search?.

Any help will be appreciated.

1
You don't have person_name.raw field in your mapping ?tricky
In mapping we have person_name with type text as follows: person_name”: { “type”: “text” }kgangadhar
You need to have the type keyword, which can be used for sorting. You can have a raw nested field type as @tricky suggested. See elastic.co/guide/en/elasticsearch/reference/current/…Aman B
Also if you don't define a mapping, now ES automatically creates the keyword field for any text field discuss.elastic.co/t/…Aman B
@AmanB, Thanks for your time, As i mentioned for person_name we have mapping as mentioned in the above comment, we already have millions records which will be affected if we change mapping now, is there any other ways to sort without modifying mapping?kgangadhar

1 Answers

10
votes

There are two ways to accomplish what you need.

  1. Add a new field multi-fields. When use multi-fields, every time you index a new field, elasticsearch will automatically apply different analyser logic for the field you are referring to. The raw field will not be analyzed, meaning it will be one term in total, thus it can be used for sort. In order to do this you'll have to update your mapping and then use the reindex api in order to update your data (you basically create a new index and then switch your application to use the new index instead the old, in order to do this with no downtime you can use an alias). Another way to update the index without creating a new one is to use the update_by_query api.
  2. If you just want this sort to work without changing anything you could use scripting. Basically you will pick the saved value and do the sort based on that. But this is not performant for extended use. This is quick and dirty, so treat with care.

All the links point to the official documentation of elasticsearch.