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


    JSONField

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

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    保存和查询None值

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

    保存None值

    我们首先创建两个Dog实例

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    观察两个实例在数据库中的表现,可以发现SQL NULLJSON null是不一样的。
    在这里插入图片描述

    查询None值

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    根据键值查找

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    包含与键查找

    contains

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    contained_by

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    has_key

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    has_keys

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    has_any_keys

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

    >>> 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>]>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    xapian 搜索引擎介绍与使用入门
    mybatis-plus雪花算法增强:idworker
    设计模式的二十三招式——以入门者角度说说设计模式
    搜素题目(蓝桥杯 C++ 代码+注解)
    MatrixOne 支持多样化生态工具,持续提升开发者体验
    SpringMVC
    痞子衡嵌入式:MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制
    Java面试——单例模式(5种写法、可能存在的问题)
    在局域网里怎么在windows 10里连接到龙梦福珑2.0的Fedora 28图形界面?
    卖不动的 iPhone 16?苹果被曝销量不达预期,甚至旧 iPhone 也能体验 Apple Intelligence!...
  • 原文地址:https://blog.csdn.net/chengyikang20/article/details/136424160