用 Django 中的 jsonb 字段过滤子查询的计数进行注释

问题描述

我有一个带有 jsonb 字段的模型。这个 jsonb 字段中有一个值,可以在其他行之间共享。我正在尝试通过此 jsonb 字段过滤时获取查询的计数。

我一直试图从这个 post 借用示例的一些伪代码

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_count2,因为有两个关联的 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": '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(),)
)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...