Создание индекса на вложенном элементе JSONField для Postgres в Django

У меня есть модель Django в моем проекте python с мета-классом, детализирующим ее индексы. Мне интересно, есть ли способ создать индекс, используя вложенный путь к объекту json. В данном случае мы знаем структуру нашего json, и я хотел бы использовать индекс BTree или Hash для конкретного элемента.

Если бы я просто запускал это как необработанный sql, я бы ожидал просто сделать что-то вроде:

CREATE INDEX ON foster_data(root->'level_1'->'level_2'->>'name');

Я надеялся, что смогу сделать что-то подобное в своей модели:

from django.db import models
from django.contrib.postgres import indexes

class ParentGuardians(Facilitators): # which extends models.Model
    parent_identifier = models.IntegerField(db_column='p_id', default=None, blank=True,
                                           null=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['table_id', name='UniqueConstraint for Parents')
        ]
        indexes = [
            models.Index(fields=['p_id', ]),
            indexes.BTreeIndex(fields=[models.JSONField('{"root": {"level_1": {"level_2": "name"}}}'), ]
                        ,  name="jsonb_p_id_idx"),
        ]

или даже:

...
            indexes.BTreeIndex(fields=["root->'level_1'->'level_2'->>'name'", ]
...

Но именованное поле fields хочет только строки и только для того, чтобы они были полем верхнего уровня, определенным в модели.

I'm aware of this questions: Indexing JSONField in Django PostgreSQL but it seems more of a hack and wanted the result generated from the codebase and makemigrations, not to manually edit it. Is this possible more recently?

В Django 3.2 появилась встроенная поддержка этих индексов.

В заданном вопросе, похоже, нет определения JSONField, но если предположить, что это что-то вроде

from django.db import models

class Facilitators(models.Model):
    foster_data = models.JSONField()

Для индексации определенного ключа вы комбинируете F-выражение с JSONField path lookup на опции Meta indexes модели :

from django.contrib.postgres.fields import JSONField   

class Facilitators(models.Model):
    foster_data = models.JSONField()
    class Meta:
        indexes = [
            models.Index(models.F("foster_data__root__level_1__level2__name"), name="foster_data__root__level_1__level2__name_idx"),
        ]

Это создаст индекс B-дерева. Если вы добавляете их к существующей модели, убедитесь, что makemigrations и migrate.

См. также этот ответ https://stackoverflow.com/a/74619523/

Вернуться на верх