sql >> Database >  >> RDS >> PostgreSQL

Een Gin-index maken met Trigram (gin_trgm_ops) in het Django-model

Ik heb een 12/2020-artikel gevonden die de nieuwste versie van Django ORM als zodanig gebruikt:

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

Als je, net als de originele poster, een index wilde maken die werkt met icontains, dan moet je de UPPER() van de kolom indexeren, wat een speciale behandeling vereist van 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',
            )
        ]

Geïnspireerd door een oud artikel over dit onderwerp kwam ik terecht bij een huidige wat de volgende oplossing geeft voor een GistIndex :

Update:Vanaf Django-1.11 lijken dingen eenvoudiger te zijn, zoals dit antwoord en django-documenten stel voor:

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

Van Django-2.2 , een attribuut opclasses zal beschikbaar zijn in de class Index(fields=(), name=None, db_tablespace=None, opclasses=()) voor dit doel.

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

Die je dan als volgt in je modelklasse kunt gebruiken:

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

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


  1. Laravel 5.5 pivot join om pivot-waarden te krijgen met het belangrijkste MySQL-resultaat

  2. Hoe een vergelijkbare waarde in Oracle te krijgen?

  3. Hoe een verouderde Oracle Data Provider verwijderen?

  4. SQL ORDER BY:De 5 do's en don'ts om gegevens als een professional te sorteren