Django中如何筛选JSONField内大于指定日期的多日期数据
Django JSONField 筛选包含指定日期之后的记录
假设你的模型定义如下:
from django.db import models class MyModel(models.Model): dates = models.JSONField() # Django 3.1+ 可用,低版本需用 django.contrib.postgres.fields.JSONField
方法一:PostgreSQL 原生查询(高效推荐)
如果项目使用PostgreSQL作为数据库,利用其JSONB原生支持可高效实现筛选:
方式1:ORM子查询实现
from django.db.models import Exists, OuterRef, Func from django.db.models.fields import TextField target_date = "2022-10-01" # 子查询展开JSON数组,筛选其中日期大于目标值的记录 subquery = MyModel.objects.filter( id=OuterRef('id') ).annotate( date_element=Func(F('dates'), function='jsonb_array_elements_text', output_field=TextField()) ).filter( date_element__gt=target_date ) # 主查询获取符合条件的记录 results = MyModel.objects.filter(Exists(subquery)).distinct()
方式2:原生SQL实现
若觉得ORM写法繁琐,直接用原生SQL更直观:
target_date = "2022-10-01" results = MyModel.objects.raw( """ SELECT DISTINCT m.* FROM myapp_mymodel m JOIN jsonb_array_elements_text(m.dates) AS d(date) ON d.date > %s """, [target_date] )
注意替换myapp_mymodel为你的模型对应的数据库表名(通常为应用名_模型名小写形式)。
方法二:跨数据库通用方案(适合小数据量)
如果使用SQLite、MySQL等对JSON支持较弱的数据库,需先取出所有记录,在Python层面过滤:
target_date = "2022-10-01" filtered_records = [] for record in MyModel.objects.all(): # 跳过数组中的空值(如示例row1里的空元素),判断是否存在大于目标日期的项 if any(date and date > target_date for date in record.dates): filtered_records.append(record)
注意事项
- 示例中row1的数组存在空值,过滤时需额外判断避免异常
- PostgreSQL方案性能远优于Python层面过滤,数据量大时优先选择
内容的提问来源于stack exchange,提问作者samrazm
相关产品推荐
相关产品推荐

