sql >> Databasteknik >  >> RDS >> PostgreSQL

Skapa ett Gin Index med Trigram (gin_trgm_ops) i Django-modellen

Jag hittade en 12/2020-artikel som använder den senaste versionen av Django ORM som sådan:

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

Om du, som den ursprungliga affischen, ville skapa ett index som fungerar med icontains, måste du indexera UPPER() i kolumnen, vilket kräver speciell hantering från 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',
            )
        ]

Inspirerad från en gammal artikel om detta ämne landade jag på en nuvarande som ger följande lösning för ett GistIndex :

Uppdatering:Från Django-1.11 verkar saker och ting vara enklare, eftersom det här svaret och django docs föreslå:

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

Från Django-2.2 , ett attribut opclasses kommer att vara tillgänglig i class Index(fields=(), name=None, db_tablespace=None, opclasses=()) för detta ändamål.

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

Som du sedan kan använda i din modellklass så här:

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

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


  1. Hur väljer man NULL om det inte finns några data och visar data om det finns?

  2. Hur kan jag få värdet på MySQL:s konfigurationsvariabel 'ft_min_word_len' med PHP?

  3. Hur upptäcker man kinesiska tecken i MySQL?

  4. UTF-8:Allmänt? Bin? Unicode?