PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Създаване на Gin индекс с триграма (gin_trgm_ops) в Django модел

Намерих статия от 12/2020 който използва най-новата версия на Django ORM като такава:

class Author(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    class Meta:
        indexes = [
            GinIndex(
                name='review_author_ln_gin_idx', 
                fields=['last_name'], 
                opclasses=['gin_trgm_ops'],
            )
        ]

Ако, подобно на оригиналния плакат, искате да създадете индекс, който работи с icontains, ще трябва да индексирате UPPER() на колоната, което изисква специална обработка от OpClass :

from django.db.models.functions import Upper
from django.contrib.postgres.indexes import GinIndex, OpClass

class Author(models.Model):
        indexes = [
            GinIndex(
                OpClass(Upper('last_name'), name='gin_trgm_ops'),
                name='review_author_ln_gin_idx',
            )
        ]

Вдъхновен от стара статия по тази тема стигнах до текущ което дава следното решение за GistIndex :

Актуализация:От Django-1.11 нещата изглеждат по-прости, тъй като този отговор и документи на django предлагам:

from django.contrib.postgres.indexes import GinIndex

class MyModel(models.Model):
    the_field = models.CharField(max_length=512, db_index=True)

    class Meta:
        indexes = [GinIndex(fields=['the_field'])]

От Django-2.2 , атрибут opclasses ще бъде наличен в class Index(fields=(), name=None, db_tablespace=None, opclasses=()) за тази цел.

from django.contrib.postgres.indexes import GistIndex

class GistIndexTrgrmOps(GistIndex):
    def create_sql(self, model, schema_editor):
        # - this Statement is instantiated by the _create_index_sql()
        #   method of django.db.backends.base.schema.BaseDatabaseSchemaEditor.
        #   using sql_create_index template from
        #   django.db.backends.postgresql.schema.DatabaseSchemaEditor
        # - the template has original value:
        #   "CREATE INDEX %(name)s ON %(table)s%(using)s (%(columns)s)%(extra)s"
        statement = super().create_sql(model, schema_editor)
        # - however, we want to use a GIST index to accelerate trigram
        #   matching, so we want to add the gist_trgm_ops index operator
        #   class
        # - so we replace the template with:
        #   "CREATE INDEX %(name)s ON %(table)s%(using)s (%(columns)s gist_trgrm_ops)%(extra)s"
        statement.template =\
            "CREATE INDEX %(name)s ON %(table)s%(using)s (%(columns)s gist_trgm_ops)%(extra)s"

        return statement

Което след това можете да използвате във вашия клас модел по следния начин:

class YourModel(models.Model):
    some_field = models.TextField(...)

    class Meta:
        indexes = [
            GistIndexTrgrmOps(fields=['some_field'])
        ]


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да получите средна стойност на „средните“ стойности в група?

  2. Оптимизиране на заявка за сходство на postgres (pg_trgm + gin индекс)

  3. Как да намеря почти подобни записи в sql?

  4. Синтактична грешка на Postgres при или близо до IF

  5. Django cache.set() причинява грешка при дублиран ключ