簡體   English   中英

Django 1.9 JSONField order_by

[英]Django 1.9 JSONField order_by

我有以下包含 JSONField 的 Django 模型:

class RatebookDataEntry(models.Model):
    data = JSONField(blank=True, default=[])
    last_update = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name_plural = 'Ratebook data entries'

數據字段包含此 json:

{
    "annual_mileage": 15000, 
    "description": "LEON DIESEL SPORT COUPE", 
    "body_style": "Coupe", 
    "range_name": "LEON", 
    "co2_gkm_max": 122, 
    "manufacturer_name": "SEAT"
}

我可以按數據字段之一對查詢集進行排序嗎? 此查詢不起作用。

RatebookDataEntry.objects.all().order_by("data__manufacturer_name")

正如 Julien 提到的,Django 尚不支持對JSONField排序。 但是可以通過RawSQL使用RawSQL PostgreSQL 函數 在 OP 的情況下:

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

從 Django 1.11 開始,可以使用django.contrib.postgres.fields.jsonb.KeyTextTransform代替RawSQL

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 1.10 上,你必須自己KeyTransform

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

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

注:之間的區別KeyTransformKeyTextTransformKeyTransform將返回對象的JSON表示,而KeyTextTransform將返回對象的值。

例如,如果data{"test": "stuff"}KeyTextTransform將返回'stuff' ,而KeyTransform將返回'"stuff"' (可以通過json.loads解析)

按照Daniil Ryzhkov 的回答和Eugene Prikazchikov 的評論,您應該能夠通過使用RawSQLOrderBy對 JSON 數據字段的 ASC 和 DESC 進行排序,而無需注釋您的RawSQL 此外,您可以通過添加LOWER來執行不區分大小寫的排序:

from django.db.models.expressions import RawSQL, OrderBy

RatebookDataEntry.objects.all().order_by(OrderBy(RawSQL("LOWER(data->>%s)", ("manufacturer_name",)), descending=True))

要比較整數字段,您可以將其轉換為整數:

RatebookDataEntry.objects.all().order_by(OrderBy(RawSQL("cast(data->>%s as integer)", ("annual_mileage",)), descending=True))

這是即將推出的功能,已經添加並將在 Django 2.1 中發布,預計將於 2018 年 8 月發布。

有關詳細信息,請參閱https://code.djangoproject.com/ticket/24747https://github.com/django/django/pull/8528

文檔沒有提到這種可能性。 看來您暫時不能使用基於 JSONfield 的 order_by。

這個問題(以及大部分答案)是針對 Django 1.9 的。 但是, Django 3.1 和更新版本在 MariaDB、MySQL、Oracle、PostgreSQL 和 SQLite 的最新版本上支持JSONField

在 JSON 字段上創建/維護索引的行為可能因數據庫引擎而異,但排序應該使用您在問題中的確切語法:

RatebookDataEntry.objects.all().order_by("data__manufacturer_name")

請注意,除非您進行進一步過濾,否則這將包括data JSONField 中的manufacturer_name鍵不存在的數據庫行。

我必須執行以下操作才能按日期排序(使用to_date )。 假設有一個在另一個值data稱為created_date (如2019年6月3日)。

RatebookDataEntry.objects.all().order_by(
        OrderBy(
            RawSQL("to_date(values->>%s, 'DD.MM.YYYY')", ("created_date",)),
            descending=True,
        )
    )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM