【Django】执行查询——查询JSONField

JSONField

本篇的例子以下面这个模型为基础:

python 复制代码
from django.db import models


class Dog(models.Model):
    name = models.CharField(max_length=200)
    data = models.JSONField(null=True)

    def __str__(self):
        return self.name

保存和查询None值

在使用JSONField时,要注意空值的处理,注意区分SQL NULLJSON null

保存None值

我们首先创建两个Dog实例

python 复制代码
from django.db.models import Value, JSONField

>>> Dog.objects.create(name="Max", data=None)  # SQL NULL.
<Dog: Max>
>>> Dog.objects.create(name="Archie", data=Value(None, JSONField()))  # JSON null.
<Dog: Archie>

观察两个实例在数据库中的表现,可以发现SQL NULLJSON null是不一样的。

查询None值

查询时,None值将被解释为JSON null,要查询SQL NULL,需要使用isnull

python 复制代码
>>> Dog.objects.filter(data=None)
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data=Value(None, JSONField()))
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data__isnull=True)
<QuerySet [<Dog: Max>]>
>>> Dog.objects.filter(data__isnull=False)
<QuerySet [<Dog: Archie>]>

对比可以发现,data=None在保存时存储为SQL NULL,查询时解释为JSON null

根据键值查找

根据json数据的键进行查找,用__连接,可以多个键连接一起,如果某个值是一个列表,要进行索引,就用整数代表该列表的索引。

例子:

python 复制代码
>>> Dog.objects.create(
...     name="Rufus",
...     data={
...         "breed": "labrador",
...         "owner": {
...             "name": "Bob",
...             "other_pets": [
...                 {
...                     "name": "Fishy",
...                 }
...             ],
...         },
...     },
... )
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": None})
<Dog: Meg>
# __连接键进行查找
>>> Dog.objects.filter(data__breed="collie")
<QuerySet [<Dog: Meg>]>
#  多个键连接进行查找
>>> Dog.objects.filter(data__owner__name="Bob")
<QuerySet [<Dog: Rufus>]>
#  某个值是一个列表,要进行索引,就用整数代表该列表的索引
>>> Dog.objects.filter(data__owner__other_pets__0__name="Fishy")
<QuerySet [<Dog: Rufus>]>
# 查询缺少的键,使用isnull查找
>>> Dog.objects.create(name="Shep", data={"breed": "collie"})
<Dog: Shep>
>>> Dog.objects.filter(data__owner__isnull=True)
<QuerySet [<Dog: Shep>]>

包含与键查找

contains

contains 查询返回的对象是那些包含给定键值对的顶层字段的对象。

python 复制代码
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.create(name="Fred", data={})
<Dog: Fred>
>>> Dog.objects.filter(data__contains={"owner": "Bob"})
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
>>> Dog.objects.filter(data__contains={"breed": "collie"})
<QuerySet [<Dog: Meg>]>

contained_by

这个可以理解为 contains 查询的反向。 要查询的对象满足这样的条件:其该字段对应的数据是传递的值的子集。

python 复制代码
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador", "owner": "Bob"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.create(name="Fred", data={})
<Dog: Fred>
>>> Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
<QuerySet [<Dog: Meg>, <Dog: Fred>]>
>>> Dog.objects.filter(data__contained_by={"breed": "collie"})
<QuerySet [<Dog: Fred>]>

has_key

返回数据顶层的键中有给定值的对象。

python 复制代码
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_key="owner")
<QuerySet [<Dog: Meg>]>

has_keys

返回数据顶层的键都包含在给定列表中的对象。

python 复制代码
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"breed": "collie", "owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_keys=["breed", "owner"])
<QuerySet [<Dog: Meg>]>

has_any_keys

返回数据顶层的键中有至少1个在给定列表中的对象,比has_keys条件更宽松。

python 复制代码
>>> Dog.objects.create(name="Rufus", data={"breed": "labrador"})
<Dog: Rufus>
>>> Dog.objects.create(name="Meg", data={"owner": "Bob"})
<Dog: Meg>
>>> Dog.objects.filter(data__has_any_keys=["owner", "breed"])
<QuerySet [<Dog: Rufus>, <Dog: Meg>]>
相关推荐
小虾米vivian3 分钟前
dmetl5 运行失败,提示违反协议?
数据库·达梦数据库
weixin_4481199419 分钟前
Datawhale Hello-Agents入门篇202512第1次作业
数据库·sql·mysql
JIngJaneIL1 小时前
基于java + vue校园快递物流管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js
廋到被风吹走1 小时前
【数据库】【MySQL】分库分表策略 分类、优势与短板
数据库·mysql·分类
嘻哈baby2 小时前
Redis高可用部署与集群管理实战
数据库·redis·bootstrap
DolphinDB智臾科技3 小时前
DolphinDB 面向金融交易与定价的统一数据模型
数据库·时序数据库
檀越剑指大厂3 小时前
时序数据库性能之战:金仓数据库如何在复杂场景下反超 InfluxDB?
数据库·时序数据库
计算机毕设VX:Fegn08953 小时前
计算机毕业设计|基于springboot + vue图书借阅管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
数据与人3 小时前
mongodb报错Sort exceeded memory limit of 104857600 bytes
数据库·mongodb
程序员鱼皮3 小时前
消息队列从入门到跑路,保姆级教程!傻子可懂
数据库·程序员·消息队列