How to sort TextFields (strings) in Django using ElasticSearch-dsl?

I cannot find the solution for this online so i hope anyone here could help.

I have a ChardField in models.py i want to sort after rebuilding the index in ElasticSearch (version 7). I'm using 'django_elasticsearch_dsl' as my pip.

I read something about adding 'fielddata' as a property in 'documents.py' or changing the TextField() type to KeywordField() but i have no idea how to do this properly.

My documents.py so far:

from django_elasticsearch_dsl import Document, fields
from django_elasticsearch_dsl.registries import registry
from .models import Journey

@registry.register_document
class JourneyDocument(Document):
    class Index:

        name = 'journeys'
        settings = {'number_of_shards': 1,
                    'number_of_replicas': 0}

    class Django:
        model = Journey # The model associated with this Document

        fields = [
            'id',
            'departure_time',
            'return_time',
            'departure_station_name',
            'return_station_name',
            'covered_distance',
            'duration',
        ]

..and my models.py is:

class Journey (models.Model):

    id = models.BigAutoField(primary_key=True)
    departure_time = models.DateTimeField(auto_now = False, auto_now_add = False, default=timezone.now)
    return_time = models.DateTimeField(auto_now=False, auto_now_add=False, default=timezone.now)
    departure_station = models.ForeignKey(Station, on_delete=models.CASCADE, related_name='departure_station')
    departure_station_name = models.CharField(max_length=50, default="-")
    return_station = models.ForeignKey(Station, on_delete=models.CASCADE, related_name='return_station')
    return_station_name = models.CharField(max_length=50, default="-")
    covered_distance = models.DecimalField(max_digits=12, decimal_places=2, validators=[MinValueValidator(10, "Covered distance of the journey has to be bigger than 10.")])
    duration = models.PositiveIntegerField(validators=[MinValueValidator(10, "Duration of the journey has to be bigger than 10s.")])

So how can i sort the query results by 'departure_station_name' in views.py like this:

s.sort("departure_station_name")

Right now im getting:

RequestError(400, 'search_phase_execution_exception', 'Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [departure_station_name] in order to load field data by uninverting the inverted index. Note that this can use significant memory.')

So far I have tried converting my field ('departure_station_name') and ('return_station_name') to KeywordFields like this:

@registry.register_document
class JourneyDocument(Document):
    class Index:

        name = 'journeys'
        departure_station_name = fields.KeywordField(fielddata=True)
        return_station_name = fields.KeywordField(fielddata=True)

        settings = {'number_of_shards': 1,
                    'number_of_replicas': 0}

    class Django:
        model = Journey # The model associated with this Document

        fields = [
            'id',
            'departure_time',
            'return_time',
            'departure_station_name',
            'return_station_name',
            'covered_distance',
            'duration',
        ]

..but to be honest i have no idea how to do it as there is limited amount of documentation or examples online.

Back to Top