Как я могу запросить и сравнить значения JSONbField на объекте? - PullRequest
1 голос
/ 11 июля 2019

У меня есть модель, которая содержит jsonbfield, и мне нужно запросить значения словаря. В запросе мне нужно убедиться, что все значения словаря равны None или что все поле имеет значение None.

Моя модель выглядит так:

MyModel(models.Model):
    date_created=DatetimeField()
    json_dict = JSONField(default=dict, null=True)

По сути, я хочу получить что-то вроде:

MyModel.objects.filter(Q(json_dict={}) |Q(json_dict=None) | Q(all(v=None for v in json_dict.values())))

Наиболее важной частью является

Q(all(v=None for v in json_dict.values()))

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

ОГРАНИЧЕНИЕ:

  • Я не знаю ключей словаря, так как они будут разными для каждого объекта в MyModel.
  • Я должен иметь возможность использовать функцию bulk_create, поэтому перезапись сохранить не вариант

Ответы [ 2 ]

1 голос
/ 11 июля 2019

По моему мнению, ваш лучший вариант, касающийся производительности , - это создать новое вычисляемое поле и отфильтровать его:

MyModel(models.Model):
    date_created=DatetimeField()
    json_dict = JSONField(default=dict, null=True)
    is_empty = BooleanField(default=True, editable=False) #<-calculated field.

    def save(self, *args, **kwargs):
        self.is_empty = ( self.metadata is None or 
                          # self.json_dict=={} or ## other checks
                          all(v is None for v in self.json_dict.values()) )
        super().save(*args, **kwargs)  

Теперь ваш запрос очень прост, а также, index friendly :

MyModel.objects.filter( is_empty = True )

Больше информации на django Переопределение предопределенных методов модели Документы.

0 голосов
/ 11 июля 2019

Как сказано в документах , вы можете только определить вызываемое по умолчанию значение, например dict. Сказав это, я считаю, что вы должны использовать dict по умолчанию и с этим вы можете фильтровать, если поле пустое. Некоторые как:

class MyModel(models.Model):
    json_dict = JSONField(default=dict)


MyModel.objects.filter(json_dict=dict())
...