通过 jsonb 字段执行 Django 连接和分组

Perform Django join and group by over jsonb fields

我 运行 遍历了所有关于注释、聚合的 Django 资源,仍然 无法理解如何使用 Django ORM 实现以下查询。

这个例子不是来自生产,而是教育,因此它可能与最佳实践不同。

我需要一个查询,该查询将输出颜色 table 中存在的每种颜色的房屋数量 table:

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 table 没有颜色的 ForeignKey,相反,它有带有 json 参数的 colorid

请注意,您设置模型的方式实际上并不需要连接(即使在 SQL 中)。同样从 ORM 的角度来看,这是一种非常奇怪的方式来拥有不明确相关的伪相关模型(即,使用 ForeignKey)。也就是说,查询集中缺少的 link 是 KeyTextTransform,它(当前)没有很好的记录但可以找到 here:

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')
)