Django 4.0+MariaDB下JSONField按id过滤返回空查询集问题
Django 4.0 + MariaDB 下 JSONField 过滤返回空 QuerySet 的排查方案
核心排查方向
1. 确认 MariaDB 版本兼容性
Django 4.0 对 MariaDB 的 JSONField 支持要求版本 ≥ 10.2.7,版本过低会导致多数 JSON 查询语法失效,先执行以下命令验证版本:
SELECT VERSION();
2. 明确 JSON 结构与数据类型
先通过调试确认目标记录的 JSON 实际结构和字段类型:
# 取目标记录打印JSON内容 obj = YourModel.objects.first() print(obj.target_360) # 查看id字段的类型(是int还是str) print(type(obj.target_360.get('id')))
比如数据库中存储的是 {"id": "123"}(字符串类型id),但你用整数 123 查询就会匹配失败,必须传入对应类型的值。
3. 针对不同结构调整查询语法
情况1:id是顶级键(如 {"id": 123})
- 直接按键查询(注意数据类型匹配):
# id为整数时 YourModel.objects.filter(target_360__id=123) # id为字符串时 YourModel.objects.filter(target_360__id='123') - 用
__contains匹配键值对:YourModel.objects.filter(target_360__contains={'id': 123})
情况2:id是嵌套键(如 {"user": {"id": 123}})
必须使用嵌套路径查询:
YourModel.objects.filter(target_360__user__id=123)
4. 排除字段为 NULL 的情况
你的字段默认值是 None(对应数据库 NULL),查询时需要明确排除 NULL 记录,否则可能因为部分记录为 NULL 干扰结果:
YourModel.objects.filter(target_360__isnull=False, target_360__id=123)
5. 直接使用 MariaDB JSON 函数兜底
如果上述方法都失效,可直接用 MariaDB 原生 JSON 函数写原生查询:
from django.db.models import RawSQL # 针对整数id YourModel.objects.raw('SELECT * FROM your_model_table WHERE JSON_EXTRACT(target_360, "$.id") = %s', [123]) # 针对字符串id,需要用JSON_UNQUOTE解析 YourModel.objects.raw('SELECT * FROM your_model_table WHERE JSON_UNQUOTE(JSON_EXTRACT(target_360, "$.id")) = %s', ['123'])
常见错误总结
- MariaDB 版本过低,不支持 Django JSONField 的查询语法
- 查询时传入的 id 类型与数据库中存储的类型不匹配(如字符串 vs 整数)
- JSON 结构嵌套,查询路径写错(如遗漏嵌套层级)
- 未排除
target_360为 NULL 的记录
内容的提问来源于stack exchange,提问作者fwirtanen
相关产品推荐
相关产品推荐

