【问题标题】:Django order_by on a nested JSONField嵌套 JSONField 上的 Django order_by
【发布时间】:2019-07-28 22:34:26
【问题描述】:

我的Product 模型上有JSONField,在这个模型中,我有嵌套字段。

例如:

"data": {
    'products':{
            "name": "ProductA", 
            "color": "Brown", 
            "price": {
                "end_user": 54,
                "credit_cart": 60
            },
            "name": "ProductB", 
            "color": "Red", 
            "price": {
                "end_user": 100,
                "credit_cart":120
             },

     }
}

我想订购嵌套的end_user 字段。

这是我的尝试:

Products.objects.order_by(RawSQL("data->>%s", ("data__price__end_user",)))

我找到了答案:

queryset = queryset.annotate(
                end_user=RawSQL("data->'products'->'price'->'->'end_user'", [])
            ).order_by('end_user')

【问题讨论】:

  • 您使用的是什么数据库后端?您需要在什么情况下订购此对象?请添加更多细节以及您想要的结果。
  • @Jane 我正在使用PostgreSQL。我有产品和产品有不止一个价格。我想订购end_user 字段。我想得到desc 的订单。我已经尝试过Products.objects.order_by(RawSQL("data->>%s", ("data__price__end_user",)))
  • 请不要在 cmets 中发布代码。您使用的是什么服务器端语言?
  • 我继续使用您提供给我的信息编辑了您的问题。您应该始终使用新信息更新您的问题。
  • 主题标题是嵌套 JSONField 上的 Django order_by。你能指望什么?显然是 Python。

标签: json django postgresql


【解决方案1】:

从 Django 1.11 开始使用 KeyTextTransform 似乎是可能的

Django => 1.11

from django.contrib.postgres.fields.jsonb import KeyTextTransform

qs = RatebookEntry.objects.all()
qs = qs.annotate(manufacturer_name=KeyTextTransform('manufacturer_name', 'data'))
qs = qs.order_by('manufacturer_name')
# or...
qs = qs.order_by('-manufacturer_name')

Django

from django.contrib.postgres.fields.jsonb import KeyTransform

class KeyTextTransform(KeyTransform):
    operator = '->>'
    nested_operator = '#>>'
    _output_field = TextField()

来源:https://stackoverflow.com/a/50046631/3345051

新实现 (2.1):https://code.djangoproject.com/ticket/24747

【讨论】:

  • 在这个问题中,用户有一个 JSONField 但我嵌套了 JSONField。例如,制造商有 2 个或更多 manufacturer_name 名称。在我的问题中,我想通过end_user DESC 或 ASC 订购。
【解决方案2】:

这是工作吗?

from django.db.models.expressions import RawSQL
RatebookDataEntry.objects.all().order_by(RawSQL("data->>%s", ("data__products__price__end_user",)))

或者这个怎​​么样:

entries = RatebookDataEntry.objects.all()
ordered_entries = sorted(entries, key=lambda x: x['data']['products']['price']['end_user'])

【讨论】:

  • 第一个答案是否定的。而对于第二个,我没有尝试,因为我不想用 Python 进行排序。我想在数据库端排序。
猜你喜欢
  • 2016-08-07
  • 2017-11-24
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 1970-01-01
  • 2021-10-07
  • 2019-07-11
  • 1970-01-01
相关资源
最近更新 更多