Search code examples
djangopostgresqlfull-text-search

How to use a tsvector field to perform ranking in Django with postgresql full-text search?


I need to perform a ranking query using postgresql full-text search feature and Django with django.contrib.postgres module.

According to the doc, it is quite easy to do this using the SearchRank class by doing the following:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')

This probably works well but this is not exactly what I want since I have a field in my table which already contains tsvectorized data that I would like to use (instead of recomputing tsvector at each search query).

Unforunately, I can't figure out how to provide this tsvector field to the SearchRank class instead of a SearchVector object on a raw data field.

Is anyone able to indicate how to deal with this?

Edit: Of course, simply trying to instantiate a SearchVector from the tsvector field does not work and fails with this error (approximately since I translated it from french):

django.db.utils.ProgrammingError: ERROR: function to_tsvector(tsvector) does not exist


Solution

  • If your model has a SearchVectorField like so:

    from django.contrib.postgres.search import SearchVectorField
    
    class Entry(models.Model):
        ...
        search_vector = SearchVectorField()
    

    you would use the F expression:

    from django.db.models import F
    
    ...
    Entry.objects.annotate(
        rank=SearchRank(F('search_vector'), query)
    ).order_by('-rank')