Creating a Gin Index with Trigram (gin_trgm_ops) in Django model

后端 未结 5 1720
轻奢々
轻奢々 2021-02-02 01:29

The new TrigramSimilarity feature of the django.contrib.postgres was great for a problem I had. I use it for a search bar to find hard to spell latin names. The problem is that

5条回答
  •  自闭症患者
    2021-02-02 01:59

    To make Django 2.2 use the index for icontains and similar searches:

    Subclass GinIndex to make an case insensitive index (uppercasing all field values):

    from django.contrib.postgres.indexes import GinIndex
    
    class UpperGinIndex(GinIndex):
    
        def create_sql(self, model, schema_editor, using=''):
            statement = super().create_sql(model, schema_editor, using=using)
            quote_name = statement.parts['columns'].quote_name
    
            def upper_quoted(column):
                return f'UPPER({quote_name(column)})'
            statement.parts['columns'].quote_name = upper_quoted
            return statement
    

    Add the index to your model like this, including kwarg name which is required when using opclasses:

    class MyModel(Model):
        name = TextField(...)
    
        class Meta:
            indexes = [
                UpperGinIndex(fields=['name'], name='mymodel_name_gintrgm', opclasses=['gin_trgm_ops'])
            ]
    

    Generate the migration and edit the generated file:

    # Generated by Django 2.2.3 on 2019-07-15 10:46
    from django.contrib.postgres.operations import TrigramExtension  # <<< add this
    from django.db import migrations
    import myapp.models
    
    
    class Migration(migrations.Migration):
    
        operations = [
            TrigramExtension(),   # <<< add this
            migrations.AddIndex(
                model_name='mymodel',
                index=myapp.models.UpperGinIndex(fields=['name'], name='mymodel_name_gintrgm', opclasses=['gin_trgm_ops']),
            ),
        ]
    

提交回复
热议问题