How do you incrementally add lexeme/s to an existing Django SearchVectorField document value through the ORM?

You can add to an existing Postgresql tsvector value using ||, for example:

UPDATE acme_table 
SET _search = 
    _search || to_tsvector('english', 'some new words to add to existing ones') 
WHERE id = 1234;

Is there any way to access this functionality via the Django ORM? I.e. incrementally add to an existing SearchVectorField value rather than reconstruct from scratch?

The issue I'm having is the SearchVectorField property returns the tsvector as a string. So when I use the || operator as +, eg:

from django.contrib.postgres.search import SearchVector

instance.my_tsvector_prop += SearchVector(["new", "words"], weight="A", config='english')

I get the error:

TypeError: SearchVector can only be combined with other SearchVector instances, got str.

Because:

type(instance.my_tsvector_prop) == str

A fix to this open Django bug whereby a SearchVectorField property returns a SearchVector instance would probably enable this, if possible. (Although less efficient than combining in the database. This update will run asynchronously so performance is not too important.)

MyModel.objects
    .filter(pk=1234)
    .update(my_tsvector_prop=
        F("my_tsvector_prop") + 
        SearchVector(
            ["new_field_name"], 
            weight="A", 
            config='english')
        )

Returns:

FieldError: Cannot resolve expression type, unknown output_field

Another solution would be to run a raw SQL UPDATE, although I'd rather do it through the Django ORM if possible as our tsvector fields often reference values many joins away, so it'd be nice to find a sustainable solution.

Back to Top