Django中JsonField字典列表的ILIKE模糊查询实现咨询
无需原生SQL的实现方案
针对Django JsonField数组内字典key值的全局模糊查询,有两种纯ORM的实现方式,无需手写原生SQL:
方案一:数组展开+子查询(兼容JsonField)
通过自定义数据库函数展开thing数组,再用Exists子查询判断是否存在匹配元素:
from django.db.models import Exists, OuterRef, Func, TextField # 自定义函数:展开JSON数组中的thing元素 class JsonArrayElements(Func): function = 'json_array_elements' template = "%(function)s(%(expressions)s::json -> 'thing')" output_field = TextField() # 构造子查询,检查当前对象的thing数组中是否有key包含目标字符串 subquery = ClassName.objects.filter( id=OuterRef('id'), # 提取展开后元素的key值,进行icontains匹配 data=Func( JsonArrayElements('data'), function='->>', template="%(expressions)s ->> 'key'", output_field=TextField() ).icontains('wo') ) # 执行主查询,只保留存在匹配的对象 matched_objects = ClassName.objects.filter(Exists(subquery))
方案二:JSONPath查询(PostgreSQL+JSONBField推荐)
如果项目使用PostgreSQL,且字段定义为JSONBField(比JsonField更高效),可直接用JSONPath正则匹配实现:
from django.db.models import Func, BooleanField # 自定义函数:使用JSONPath检查模糊匹配 class JsonPathLike(Func): function = 'jsonb_path_exists' # JSONPath表达式:匹配thing数组中任意元素的key,不区分大小写包含"wo" template = "%(function)s(%(expressions)s, '$.thing[*].key like_regex \"wo\" flag \"i\"')" output_field = BooleanField() # 直接过滤符合条件的对象 matched_objects = ClassName.objects.filter(JsonPathLike('data'))
关键说明
- 方案一兼容标准
JsonField,通过模拟json_array_elements的行为实现数组遍历,适用于多数支持JSON函数的数据库。 - 方案二依赖PostgreSQL的JSONB特性,语法更简洁、查询效率更高,推荐在PostgreSQL环境下使用。
- 两种方案完全基于Django ORM,避免了手写原生SQL的维护成本。
内容的提问来源于stack exchange,提问作者lebedev
相关产品推荐
相关产品推荐

