4

I have the next model:

from django.contrib.postgres.fields import JSONField
from django.contrib.postgres.fields.jsonb import KeyTextTransform
from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import SearchVectorField, SearchVector
from django.db import models


class ProfileUser(models.Model):
    name = JSONField()
    search_vector = SearchVectorField(null=True)

    class Meta:
        indexes = [GinIndex(fields=["search_vector"], name="user_full_name_gin_idx")]

    def save(self, *args, **kwargs):
        super(ProfileUser, self).save(*args, **kwargs)
        ProfileUser.objects.filter(pk=self.pk).update(search_vector=SearchVector('name'))

        # I have tried this, but this does not work.
        # ProfileUser.objects.filter(pk=self.pk).update(search_vector=SearchVector(KeyTextTransform('name', 'name')))

And name looks like [{'name': 'Random Name', 'lang': 'en'}, {'name': 'Какое-то Имя', 'lang': 'ru'}].

Currently the code above indexes both name and lang keys. Is it possible using Django to index just name key? I found how to workaround this using SQL directly, but I just want to know, if it is possible to do that just via Django.

I use Django 2.2 and PostgreSQL 12.

3 Answers 3

3

Functional indexes is going to be available in Django 3.2 in April. This finally should allow to build needed indexes from Django.

Sign up to request clarification or add additional context in comments.

Comments

2

In PostgreSQL, the feature which allows creating indices on parts of a JSON-structured field is called expression index. It needs to be used together with GIN index to achieve the desired effect. Such a usage is briefly mentioned in the jsonb documentation:

CREATE INDEX idxgintags ON api USING GIN ((jdoc -> 'tags'));

To the best of my knowledge, currently (December 2020) the only way to create such an index in Django is to issue the SQL statements manually.

However, there is an open ticket which asks for adding the support for expression indices to Django. The feature has been accepted but there is no patch yet and the ticket has not been updated for more than a year.

1 Comment

Support was added in 3.2 in this PR: github.com/django/django/pull/11929 However, I'm still confused on the proper syntax.
1

Yes, it is possible, you can read the documentation for django indexing here: https://docs.djangoproject.com/en/3.0/ref/models/indexes/

Change this line:

indexes = [GinIndex(fields=["search_vector"], name="user_full_name_gin_idx")]

to this:

indexes = [GinIndex(fields=["name"], name="user_full_name_gin_idx")]

1 Comment

This would not help, because fields=["name"] includes both fields (name and lang). fields means field names of model (not a key of JSON).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.