Выполните объединение и группирование Django по полям jsonb - PullRequest
0 голосов
/ 01 сентября 2018

Я просмотрел все источники Django об аннотациях, агрегации, не могу понять, как реализовать следующий запрос с Django ORM.

Этот пример не из производства, а скорее образовательный, поэтому он может отличаться от лучших практик.

Мне нужен запрос, который будет выводить количество домов на каждый цвет в таблице «Цвета»:

select
    clr.id as colorId, count(*) as count

from colors as clr
inner join houses as c
on clr.id = cast(c.parameters ->> 'colorId' as int)
group by colorId;

Схема данных определяется следующим образом:

CREATE TABLE colors (
  id serial primary key NOT NULL,
  name text NOT NULL
);

CREATE TABLE houses (
  id serial primary key NOT NULL,
  parameters jsonb NOT NULL
);

insert into colors (id, name) values

(1, 'red'),
(2, 'green'),
(3, 'blue'),
(4, 'other');

insert into houses (parameters) values

('{"price": 1000, "colorId": 1}'),
('{"price": 2000, "colorId": 2}'),
('{"price": 2500, "colorId": 2}'),
('{"price": 3000, "colorId": 3}'),
('{"price": 3100, "colorId": 3}'),
('{"price": 3200, "colorId": 3}');

Какая будет реализация с Django ORM? Простые запросы довольно просты, но мне не хватает кое-чего, чтобы понять об агрегации и аннотации по полям jsonb

Вот модель:

from django.contrib.postgres.fields import JSONField, TextField
from django.db import models

class Color(models.Model):
    name = models.TextField()

class House(models.Model):
    parameters = models.JSONField()

Этот запрос должен выглядеть так:

from django.db.models import Count
Houses.objects.values('color').annotate(dcount=Count('color'))

Но таблица Houses не имеет ForeignKey to Colors, вместо этого она имеет colorid с параметрами json

1 Ответ

0 голосов
/ 02 сентября 2018

Обратите внимание, что при настройке модели вам на самом деле не требуется объединение (даже в SQL). Также с точки зрения ORM это довольно странный способ иметь псевдо-связанные модели, которые не связаны явно (то есть с ForeignKey). Тем не менее, отсутствующей ссылкой в ​​вашем наборе запросов является KeyTextTransform, который (в настоящее время) не очень хорошо задокументирован, но его можно найти здесь :

from django.contrib.postgres.fields.jsonb import KeyTextTransform
from django.db.models import Count

Houses.objects.annotate(
    color_id=KeyTextTransform('colorId', 'parameters')
).values(
    'color_id'
).annotate(
    dcount=Count('color_id')
)
...