Django4.0 執(zhí)行查詢-查詢JSONField

2022-03-16 17:33 更新

?JSONField ?里的查找實(shí)現(xiàn)是不一樣的,主要因?yàn)榇嬖阪I轉(zhuǎn)換。為了演示,我們將使用下面這個(gè)例子:

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值

與其他字段一樣,將 ?None ?作為字段的值存儲(chǔ)為 SQL 的 ?NULL?。雖然不建議這樣做,但可以使用 ?Value('null')? 來存儲(chǔ) JSON 的 ?null ?值。
無論存儲(chǔ)哪種值,當(dāng)從數(shù)據(jù)庫檢索時(shí),JSON 標(biāo)量 ?null ?的 Python 表示法與 SQL 的 ?NULL ?相同,即 ?None?。因此,可能很難區(qū)分它們。
這只適用于 ?None ?值作為字段的頂級值。如果 ?None ?被保存在列表或字典中,它將始終被解釋為 JSON 的 ?null ?值。
當(dāng)查詢時(shí),?None ?值將一直被解釋為 JSON 的 ?null?。要查詢 SQL 的 ?NULL?,請使用 ?isnull ?:

>>> Dog.objects.create(name='Max', data=None)  # SQL NULL.
<Dog: Max>
>>> Dog.objects.create(name='Archie', data=Value('null'))  # JSON null.
<Dog: Archie>
>>> Dog.objects.filter(data=None)
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data=Value('null'))
<QuerySet [<Dog: Archie>]>
>>> Dog.objects.filter(data__isnull=True)
<QuerySet [<Dog: Max>]>
>>> Dog.objects.filter(data__isnull=False)
<QuerySet [<Dog: Archie>]>

除非你確定要使用 SQL 的 ?NULL ?值,否則請考慮設(shè)置 ?null=False? 并為空值提供合適的默認(rèn)值,例如 ?default=dict? 。

注意:保存 JSON 的 ?null ?值不違反 Django 的 ?null=False? 。

鍵、索引和路徑轉(zhuǎn)換

為了查詢給定的字典鍵,請將該鍵作為查詢名:

>>> 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>]>

可以將多個(gè)鍵鏈接起來形成一個(gè)路徑查詢:

>>> Dog.objects.filter(data__owner__name='Bob')
<QuerySet [<Dog: Rufus>]>

如果鍵是個(gè)整型,那么它將在數(shù)組中被解釋成一個(gè)索引:

>>> Dog.objects.filter(data__owner__other_pets__0__name='Fishy')
<QuerySet [<Dog: Rufus>]>

如果要查詢的鍵與另一個(gè)查詢的鍵名沖突,請改用 ?contains ?來查詢。
如果查詢時(shí)缺少鍵名,請使用 ?isnull ?查詢:

>>> Dog.objects.create(name='Shep', data={'breed': 'collie'})
<Dog: Shep>
>>> Dog.objects.filter(data__owner__isnull=True)
<QuerySet [<Dog: Shep>]>

上面給出的例子隱式地使用了 ?exact ?查找。?Key?,?Index?和?Path?轉(zhuǎn)換也可以用:?icontains?、?endswith?、?iendswith?、?iexact?、?regex?、?iregex?、?startswith?、?istartswith?、?lt?、?lte?、?gt?、?gte ?以及 包含與鍵查找 。

由于?Key-Path?查詢的工作方式,?exclude()? 和 ?filter()? 不能保證產(chǎn)生詳盡的集合。如果你想包含沒有路徑的對象,請?zhí)砑??isnull ?查找。

包含與鍵查詢

contains

?JSONField ?上的 ?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>]>

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>]>

has_key

返回給定的鍵位于數(shù)據(jù)頂層的對象。例如:

>>> 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

返回所有給定的鍵位于數(shù)據(jù)頂層的對象。例如:

>>> 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

返回任何給定的鍵位于數(shù)據(jù)頂層的對象。例如:

>>> 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>]>


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)