1

I want to setup a Postgres "stored generated columns" with indexing to have full text search on two fields of a model. I created the generated column getting help from this tutorial, but when setting gin index on the column, I get this:

django.core.exceptions.FieldDoesNotExist: Article has no field named 'vector_column'. The app cache isn't ready yet, so if this is an auto-created related field, it won't be available yet.

Here's my Article model:

class Article(models.Model):
    title = models.CharField(...)
    content = models.TextField(...)
    class Meta:
        indexes = [GinIndex(fields=['vector_column'])]

and my custom sql in migration file:

    operations = [
        migrations.RunSQL(
            sql='''
              ALTER TABLE articles_article ADD COLUMN vector_column tsvector GENERATED ALWAYS AS (
                setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
                setweight(to_tsvector('english', coalesce(content,'')), 'B')
              ) STORED;
            ''',

            reverse_sql='''
              ALTER TABLE articles_article DROP COLUMN vector_column;
            '''
        ),
    ]

Is it possible to set index from Django? Seems Django needs the field to be defined on the model but that's not how generated column works. If not, what's the correct way of setting the proper index (mentioned in this Postgres doc, the one at the end of the page) in migration files?

6
  • If you create a generated column manually via a migration you can't define the index in your model's Meta, the article only adds the index this way when using the SearchVectorField Commented Dec 31, 2021 at 18:29
  • @IainShelvington So then I should manually create the index in migration files? Commented Dec 31, 2021 at 18:37
  • 1
    Yes, that is the only way to add an index to the column since Django does not know about it Commented Dec 31, 2021 at 18:42
  • Thank you very much for your comments. If you submit these commit along with samples for sql and reverse_sql parts, I would accept that as the answer. Commented Dec 31, 2021 at 18:46
  • Did you see this? Commented Jan 1, 2022 at 1:28

1 Answer 1

2

As Iain said in comments, index must be handled in migrations. I just added another migrations to operations array:

    operations = [
        migrations.RunSQL(
            sql='''
              ALTER TABLE articles_article ADD COLUMN vector_column tsvector GENERATED ALWAYS AS (
                setweight(to_tsvector('english', coalesce(title, '')), 'A') ||
                setweight(to_tsvector('english', coalesce(content,'')), 'B')
              ) STORED;
            ''',

            reverse_sql='''
              ALTER TABLE articles_article DROP COLUMN vector_column;
            '''
        ),
        migrations.RunSQL(
            sql='''
                CREATE INDEX textsearch_idx ON articles_article USING GIN (vector_column);
            ''',

            reverse_sql='''
                DROP INDEX IF EXISTS textsearch_idx;
            '''
        ),
    ]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.