es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Creando un índice Gin para una columna generada almacenada en Postgres en Django.

Quiero configurar una columna generada almacenada de Postgres con indexación para tener una búsqueda de texto completo en dos campos de un modelo. Creé la columna generada obteniendo ayuda de este tutorial, pero al configurar el índice gin en la columna, obtengo esto:

django.core.exceptions.FieldDoesNotExist: Article no tiene un campo llamado ‘vector_column’. La caché de la aplicación aún no está lista, por lo que si este es un campo relacionado creado automáticamente, aún no estará disponible.

Aquí está mi modelo Article:

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

y mi SQL personalizado en el archivo de migración:

    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;
            ''',
        ),
    ]

¿Es posible configurar el índice desde Django? Parece que Django necesita que el campo esté definido en el modelo, pero así no funciona una columna generada. Si no es posible, ¿cuál es la forma correcta de configurar el índice adecuado (mencionado en esta documentación de Postgres, al final de la página) en archivos de migración?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El mensaje de error sugiere que Django espera que se defina un campo vector_column en el modeloArticle, lo cual no es cómo funcionan las columnas generadas en PostgreSQL.

    Para establecer el índice adecuado para la búsqueda de texto completo en los campos title y content del modeloArticle utilizando una columna generada, puede definir un índice de base de datos personalizado en el archivo de migración. Aquí hay un ejemplo de cómo hacerlo:

    from django.contrib.postgres.operations import CreateExtension, RawSQL
    
    class Migration(migrations.Migration):
    
        dependencies = [
            ('articles', '0001_initial'),
            ('postgres', '0001_initial'), # for CreateExtension operation
        ]
    
        operations = [
            CreateExtension('pg_trgm'),
            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;
                '''
            ),
            RawSQL(
                '''
                CREATE INDEX articles_article_vector_column_gin_idx
                ON articles_article
                USING gin(vector_column gin_trgm_ops);
                ''',
                []),
        ]
    

    En este ejemplo, la operación RawSQL se utiliza para crear un índice gin en la columna generada vector_column utilizando la clase de operador "gin_trgm_ops", que proporciona soporte para búsqueda de texto completo con la extensión pg_trgm.

    Tenga en cuenta que la operación CreateExtension también se incluye para asegurarse de que la extensión pg_trgm esté instalada antes de crear el índice.

    Asegúrese de ajustar el archivo de migración y el nombre del modelo de acuerdo con el esquema de su proyecto.

Comments are closed.