用 Django 中的 jsonb 字段过滤子查询的计数进行注释
Annotating with the count of a subquery filtering by jsonb fields in Django
我有一个带有 jsonb 字段的模型。此 jsonb 字段中有一个值可以在其他行之间共享。我正在尝试通过此 jsonb 字段过滤时获取子查询的计数。
我一直在尝试从中借用示例的一些伪代码。
alpha_qs = MyModel.objects.filter(class_id="ALPHA")
# unnest jsonb field so I can leverage it via OuterRef
alpha_qs = alpha_qs.annotate(nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field"))
related_beta_subquery = MyModel.objects.filter(class_id="BETA", a_jsonb_field__nested_value_id=OuterRef("nested_value_id"))
related_beta_subquery_count = related_beta_subquery.annotate(count=Count("*")).values("count")
alpha_qs = alpha_qs.annotate(related_beta_count=Subquery(related_beta_subquery))
使用此示例数据,我希望顶级实例的 related_beta_count
为 2
,因为有两个关联的 beta 具有相同的 nested_value_id
.
{
"class_id": "ALPHA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'zyz'
}
}
我一直收到以下错误,但无法解决。
ProgrammingError: operator does not exist: jsonb = text
LINE 1: ...d AND (U0."a_jsonb_field" -> 'nested_value_id') = ("my_model...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
我用它来处理我的用例。我不认为自己精通 Django,所以可能有更简洁的方法来实现这一点。
# Get initial queryset
alpha_qs = MyModel.objects.filter(class_id="ALPHA")
# Pull nested jsonb value out via annotation/KeyTextTransform
alpha_qs = alpha_qs.annotate(nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field"))
related_beta_subquery = (
MyModel.objects.filter(
class_id="BETA"
)
# Pull out nested jsonb for subquery as well
.annotate(
nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field")
)
# Filter to ensure these BETA models have a matched nested_value_id to my ALPHA models
.filter(
nested_value_id=OuterRef("nested_value_id")
)
# This was honestly the harder part that took a lot of trial and error
.order_by()
.values("nested_value_id")
.annotate(count=Count("*"))
.values("count")
)
alpha_qs = alpha_qs.annotate(
count=Case(
# This Case statement is mostly just bulletproofing. May be unnecessary for your use case
When(a_jsonb_field__has_key="nested_value_id", then=Subquery(related_beta_subquery)),
default=Value(0),
output_field=IntegerField(),
)
)
我有一个带有 jsonb 字段的模型。此 jsonb 字段中有一个值可以在其他行之间共享。我正在尝试通过此 jsonb 字段过滤时获取子查询的计数。
我一直在尝试从中借用示例的一些伪代码
alpha_qs = MyModel.objects.filter(class_id="ALPHA")
# unnest jsonb field so I can leverage it via OuterRef
alpha_qs = alpha_qs.annotate(nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field"))
related_beta_subquery = MyModel.objects.filter(class_id="BETA", a_jsonb_field__nested_value_id=OuterRef("nested_value_id"))
related_beta_subquery_count = related_beta_subquery.annotate(count=Count("*")).values("count")
alpha_qs = alpha_qs.annotate(related_beta_count=Subquery(related_beta_subquery))
使用此示例数据,我希望顶级实例的 related_beta_count
为 2
,因为有两个关联的 beta 具有相同的 nested_value_id
.
{
"class_id": "ALPHA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'abc'
}
}
{
"class_id": "BETA",
"a_jsonb_field": {
"nested_value_id": 'zyz'
}
}
我一直收到以下错误,但无法解决。
ProgrammingError: operator does not exist: jsonb = text
LINE 1: ...d AND (U0."a_jsonb_field" -> 'nested_value_id') = ("my_model...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
我用它来处理我的用例。我不认为自己精通 Django,所以可能有更简洁的方法来实现这一点。
# Get initial queryset
alpha_qs = MyModel.objects.filter(class_id="ALPHA")
# Pull nested jsonb value out via annotation/KeyTextTransform
alpha_qs = alpha_qs.annotate(nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field"))
related_beta_subquery = (
MyModel.objects.filter(
class_id="BETA"
)
# Pull out nested jsonb for subquery as well
.annotate(
nested_value_id=KeyTextTransform("nested_value_id", "a_jsonb_field")
)
# Filter to ensure these BETA models have a matched nested_value_id to my ALPHA models
.filter(
nested_value_id=OuterRef("nested_value_id")
)
# This was honestly the harder part that took a lot of trial and error
.order_by()
.values("nested_value_id")
.annotate(count=Count("*"))
.values("count")
)
alpha_qs = alpha_qs.annotate(
count=Case(
# This Case statement is mostly just bulletproofing. May be unnecessary for your use case
When(a_jsonb_field__has_key="nested_value_id", then=Subquery(related_beta_subquery)),
default=Value(0),
output_field=IntegerField(),
)
)