Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs 菜单
Docs 主页
/ / /
Django MongoDB后端
/

指定查询

在本指南中,您可以学习;了解如何使用 Django MongoDB后端来指定数据库查询。

您可以通过创建查询过滤来优化查询返回的文档设立。查询过滤是一个表达式,用于指定MongoDB在读取或写入操作中用于匹配文档的搜索条件。 在查询过滤中,您可以提示 Django MongoDB后端搜索与您的查询完全匹配的文档,也可以编写查询筛选器以Express更复杂的匹配条件。

Django QuerySet API提供了允许您检索模型对象的方法。 要运行MongoDB 数据库查询,请在模型管理器上调用 QuerySet 方法。 Manager 类处理数据库操作,并允许您通过引用 Django 模型与MongoDB数据交互。 默认情况下,Django 会向每个模型类添加一个名为 objectsManager

QuerySet 分配给变量时,在您评估该变量之前,Django MongoDB后端不会执行该操作。 对 QuerySet 求值后,Django 将查询结果保存在 QuerySet缓存中。 QuerySet 的未来评估将使用缓存的结果。

提示

要学习;了解有关 DjangoQuerySet API的详情,请参阅QuerySet Django 文档中的 。

本指南中的示例使用Movie 模型,该模型表示Atlas示例数据集中的sample_mflix.movies 集合。Movie 模型包含嵌入式 Award 模型,作为其 awards字段的值。 这些模型类具有以下定义:

from django.db import models
from django_mongodb_backend.models import EmbeddedModel
from django_mongodb_backend.fields import EmbeddedModelField, ArrayField
class Award(EmbeddedModel):
wins = models.IntegerField(default=0)
nominations = models.IntegerField(default=0)
text = models.CharField(max_length=100)
class Movie(models.Model):
title = models.CharField(max_length=200)
plot = models.TextField(blank=True)
runtime = models.IntegerField(default=0)
released = models.DateTimeField("release date", null=True, blank=True)
awards = EmbeddedModelField(Award)
genres = ArrayField(models.CharField(max_length=100), null=True, blank=True)
imdb = models.JSONField(null=True)
class Meta:
db_table = "movies"
managed = False
def __str__(self):
return self.title

Movie 模型包括一个内部 Meta 类(用于指定模型元数据)和一个 __str__() 方法(用于定义模型的字符串表示形式)。 要学习;了解这些模型功能,请参阅创建模型指南中的 定义模型。

您可以使用Python交互式Shell来运行代码示例。 要进入Shell ,请从项目的根目录运行以下命令:

python manage.py shell

进入Python Shell后,请确保导入以下模型和模块:

from <your application name>.models import Movie, Award
from django.utils import timezone
from datetime import datetime

要学习;了解如何创建使用 Movie 模型和Python交互式Shell与MongoDB文档交互的Django应用程序,请访问入门教程

要查询MongoDB数据,请在模型管理器上调用 QuerySet 方法,并在查询过滤中指定匹配条件。

本部分介绍如何使用 QuerySet API中的以下方法:

要从集合中检索所有文档,请在模型管理器上调用 all() 方法。

以下示例调用 all() 方法来检索sample_mflix.movies集合中的所有文档:

Movie.objects.all()
<QuerySet [<Movie: The Great Train Robbery>, <Movie: A Corner in Wheat>,
<Movie: Winsor McCay, the Famous Cartoonist of the N.Y. Herald and His Moving Comics>,
<Movie: Traffic in Souls>, <Movie: Gertie the Dinosaur>,
<Movie: In the Land of the Head Hunters>, <Movie: The Perils of Pauline>,
<Movie: The Italian>, <Movie: Regeneration>, <Movie: Civilization>,
'...(remaining elements truncated)...']>

要查询集合是否存在与一设立条件匹配的文档,请对模型管理器调用 filter() 方法。 将查询过滤传递给指定查询条件的 filter() 方法。

以下示例调用 filter() 方法来查询sample_mflix.movies集合中 runtime 值为 300 的文档:

Movie.objects.filter(runtime=300)
<QuerySet [<Movie: Wild Palms>, <Movie: Streets of Laredo>,
<Movie: The Way We Live Now>]>

要从集合中检索一份文档,请在模型管理器上调用 get() 方法。 将查询过滤传递给指定查询条件的 get() 方法。

重要

如果您的查询不匹配任何文档或匹配多个文档,则 get() 方法会产生错误。 要从可能匹配多个文档的查询中检索一个文档,请使用 first() 方法。

以下示例调用 get() 方法来检索title 值为 "Finding Nemo" 的文档:

Movie.objects.get(title="Finding Nemo")
<Movie: Finding Nemo>

要查询集合是否有不符合搜索条件的文档,请对模型管理器调用 exclude() 方法。 将排除条件作为参数传递给 exclude() 方法。

以下示例调用 exclude() 方法从结果中排除 datetime(1980, 1, 1)(一月 1,1980)之前发布的文档:

Movie.objects.exclude(released__lt=timezone.make_aware(datetime(1980, 1, 1)))
<QuerySet [<Movie: The Iron Horse>, <Movie: Le grand jeu>,
<Movie: The Devil Is a Woman>, <Movie: Children in the Wind>,
<Movie: Too Much Johnson>, <Movie: Dots>, <Movie: The Blood of Jesus>,
<Movie: The Land>, <Movie: The Brothers and Sisters of the Toda Family>,
<Movie: Begone Dull Care>, '...(remaining elements truncated)...']>

提示

前面的示例使用 lt字段查找来查询集合。 要学习;了解有关比较查找的更多信息,请参阅本指南中的“使用比较查找”部分。

如果要运行Django 的查询API不支持的复杂查询,可以使用 raw_aggregate() 方法。 此方法允许您在MongoDB聚合管道中指定查询条件,并将其作为参数传递给 raw_aggregate()

要学习;了解如何运行原始数据库查询,请参阅执行原始数据库查询指南。

您可以在查询过滤中使用字段查找来进一步优化查询条件。字段查找可让您明确正在查询的字段与要查询的值之间的关系。 使用以下语法指定字段查找:

Model.objects.filter(<field name>__<lookup type>=<value>)

您可以使用不同的查找类型执行高级查询,例如部分文本匹配、大量元素查询、正则表达式匹配以及日期时间字段的年份值匹配。

提示

要查看查找类型的完整列表,请参阅 QuerySetDjango API参考中的字段查找。

本节介绍如何通过以下方式优化查询筛选器:

下表描述了可用于运行包含文本值的特定匹配条件的查询的一些查找类型:

查找类型
说明

exact

Specifies an exact text match. If you do not provide a lookup type in your query filter, Django MongoDB Backend uses this type by default.
You can specify a case-insensitive exact text match by using iexact.

contains

Specifies a partial text match.
You can specify a case-insensitive partial text match by using icontains.

startswith

Matches field values that begin with the specified text.
You can specify a case-insensitive partial text match by using istartswith.

endswith

Matches field values that end with the specified text.
You can specify a case-insensitive partial text match by using iendswith.

以下示例使用 contains 查找来查询plot 值包含文本 "coming-of-age" 的文档:

Movie.objects.filter(plot__contains="coming-of-age")
<QuerySet [<Movie: Murmur of the Heart>, <Movie: Desert Bloom>,
<Movie: Girls Town>, <Movie: Get Real>, <Movie: Man of Steel>,
<Movie: The Holy Land>, <Movie: Secondhand Lions>, <Movie: How to Be Louise>,
<Movie: Mouth to Mouth>, <Movie: Che ne sarè di noi>, <Movie: Roll Bounce>,
'...(remaining elements truncated)...']>

下表描述了可用于运行根据指定值评估字段值的查询的部分查找类型:

查找类型
说明

gt

Matches field values that are greater than the specified value.

gte

Matches field values that are greater than or equal to the specified value.

lt

Matches field values that are less than the specified value.

lte

Matches field values that are less or equal to than the specified value.

以下示例使用 lte 查找来查询runtime 值小于或等于 50 的文档:

Movie.objects.filter(runtime__lte=50)
<QuerySet [<Movie: The Great Train Robbery>, <Movie: A Corner in Wheat>,
<Movie: Winsor McCay, the Famous Cartoonist of the N.Y. Herald and His Moving Comics>,
<Movie: Gertie the Dinosaur>, <Movie: From Hand to Mouth>,
<Movie: High and Dizzy>, <Movie: One Week>, <Movie: Now or Never>,
'...(remaining elements truncated)...']>

您可以通过以下方式运行使用多组匹配条件的查询:

  • 将多个查询筛选器传递给查询方法,用逗号分隔。要查看示例,请参阅 Django 文档中的检索对象。

  • 将查询方法链接在一起。要学习;了解更多信息,请参阅 Django 文档中的链接筛选器。

  • 使用Q 对象,并用逻辑操作符分隔每个对象。要学习;了解更多信息,请参阅 Django 文档中的使用 Q 对象进行的复杂查找。

您可以使用 Q 对象来运行具有多组匹配条件的查询。 要创建 Q对象,请将查询过滤传递给 Q() 方法。 您可以将多个 Q 对象作为参数传递给查询方法,并用 OR (|)、AND (&) 或 XOR (^)操作符符分隔每个 Q对象。 您还可以通过在 Q 对象前加上 ~ 符号来取反。

此示例使用 Q 对象来查询满足以下查询条件的文档:

  • title 字段值以文本 "Funny""Laugh" 开头

  • genres 大量字段不包含值 "Comedy"

Movie.objects.filter(
(Q(title__startswith="Funny") | Q(title__startswith="Laugh"))
& ~Q(genres__contains=["Comedy"])
)
<QuerySet [<Movie: Laugh, Clown, Laugh>, <Movie: Funny Games>]>

提示

前面的示例对 ArrayField 值使用了字段查找。 有关查询ArrayField 的更多信息,请参阅本指南中的“查询 ArrayField”部分。

本节介绍如何通过以下方式修改查询结果:

您可以使用 order_by() 方法为查询结果提供排序顺序。 要指定根据给定字段的值进行升序排序,请将字段名称作为参数传递。 要指定降序排序,请将前缀为减号 (-) 的字段名称作为参数传递。

您可以将多个字段名称(以逗号分隔)传递给 order_by() 方法。 Django MongoDB后端按提供的顺序按每个字段对结果进行排序。

此示例将执行以下动作:

  • Movie 模型管理器上调用 filter() 方法以查询sample_mflix.movies集合

  • 查询 title 值以文本 "Rocky" 开头的文档

  • released字段值的升序对结果进行排序

Movie.objects.filter(title__startswith="Rocky").order_by("released")
<QuerySet [<Movie: Rocky>, <Movie: Rocky II>, <Movie: Rocky III>,
<Movie: Rocky IV>, <Movie: Rocky V>, <Movie: Rocky Marciano>,
<Movie: Rocky Balboa>]>

您可以使用 Python 的数组切片语法指定查询返回的结果数,如以下代码所示:

Model.objects.filter(<query filter>)[<start>:<end>]

<start><end> 占位符替换为表示要返回的结果子集的整数值。 起始值不包括在内,结束值包括在内。

如果省略 <start> 值,则查询会返回从第一个匹配项开始的每个结果,直到返回 <end> 值指定的数字。

如果省略 <end> 值,查询将返回每个结果,但会跳过 <start> 指定的初始结果数。

此示例将执行以下动作:

  • Movie 模型管理器上调用 filter() 方法以查询sample_mflix.movies集合

  • 查询 released 值为 datetime(2010, 7, 16) 的文档(7 月 16、2010)

  • 返回第三个和第四个结果

Movie.objects.filter(released=timezone.make_aware(datetime(2010, 7, 16)))[2:4]
<QuerySet [<Movie: Inception>, <Movie: Winter's Bone>]>

要从可能匹配多个结果的查询中检索第一个结果,请将 first() 方法链接到 filter() 方法。 将查询过滤传递给指定查询条件的 filter() 方法。

以下示例调用 filter()first() 方法在 sample_mflix.movies集合中查询genres 值为 ["Crime", "Comedy"] 的第一个文档:

Movie.objects.filter(genres=["Crime", "Comedy"]).first()
<Movie: The Crew>

本节介绍如何对以下字段类型运行查询:

您可以在模型上运行查询嵌入式模型字段的操作。 要查询这些字段,请指定模型字段和每个嵌入式字段名称,并用双下划线 (__) 分隔,直到找到要查询的字段,如以下代码所示:

Model.objects.filter(<model field>__<embedded model field>=<value>)

您还可以使用字段查找来优化嵌入式模型查询。在要查询的嵌入式模型字段之后添加查找类型,并以双下划线为前缀。

此示例使用查找来查询嵌入在 Movie 模型中的 Award 模型。 此嵌入式模型表示 sample_mflix.movies集合中的 awards字段及其嵌套的 winsnominationstext 字段。 以下代码查询 awards.wins 嵌套字段值大于 150 的文档:

Movie.objects.filter(awards__wins__gt=150)
<QuerySet [<Movie: The Lord of the Rings: The Return of the King>,
<Movie: No Country for Old Men>, <Movie: Slumdog Millionaire>,
<Movie: Boyhood>, <Movie: The Social Network>, <Movie: Inception>,
<Movie: Gravity>, <Movie: Gravity>, <Movie: The Artist>,
<Movie: 12 Years a Slave>, <Movie: Birdman: Or (The Unexpected Virtue of Ignorance)>]>

您可以使用标准查询语法查询在 ArrayField 值中的数据。 Django MongoDB后端提供了用于查询 ArrayField 值的其他字段查找类型,如下表所述:

查找类型
说明

contains

Matches fields that store the provided value as a subset of their data. This ArrayField lookup overrides the contains lookup described in the Use Text Match Lookups section of this guide.

contained_by

Matches fields that store a subset of the provided values. This lookup type is the inverse of contains.

overlap

Matches field that store any of the provided values.

len

Matches fields that store the number of values provided.

以下示例使用 overlap 查找来查询genres字段包含 ["Adventure", "Family"]大量中的任何值的文档:

Movie.objects.filter(genres__overlap=["Adventure", "Family"])
<QuerySet [<Movie: The Poor Little Rich Girl>, <Movie: Robin Hood>,
<Movie: Peter Pan>, <Movie: The Thief of Bagdad>, <Movie: Clash of the Wolves>,
<Movie: Beau Geste>, <Movie: The Black Pirate>, <Movie: The Son of the Sheik>,
<Movie: Steamboat Willie>, <Movie: The Big Trail>, <Movie: The Champ>,
'...(remaining elements truncated)...']>

您可以使用与查询JSONField EmbeddedModelField 部分所示相同的语法来查询在 值中的数据。将每个字段和嵌套字段名称链接在一起,用双下划线 (__) 分隔,直到到达要查询的字段。

以下示例查询值为 JSONFieldimdb字段,其嵌套 votes字段的值是否超过 900000

Movie.objects.filter(imdb__votes__gt=900000)
<QuerySet [<Movie: La nao capitana>, <Movie: The Godfather>,
<Movie: This Is Spinal Tap>, <Movie: Forrest Gump>, <Movie: Pulp Fiction>,
<Movie: The Shawshank Redemption>, <Movie: Se7en>,
<Movie: The Lord of the Rings: The Fellowship of the Ring>,
<Movie: The Matrix>, <Movie: Fight Club>,
<Movie: The Lord of the Rings: The Return of the King>,
<Movie: The Lord of the Rings: The Two Towers>, <Movie: The Shawshank Redemption>,
<Movie: Landet som icke èr>, <Movie: The Dark Knight>,
<Movie: The Danish Girl>, <Movie: The Dark Knight Rises>, <Movie: Inception>,
<Movie: Catching the Sun>, <Movie: Scouts Guide to the Zombie Apocalypse>,
'...(remaining elements truncated)...']>

您可以使用 KT() 表达式来注释和过滤JSONField 值中存储的数据。 KT() 表达式允许您在 JSONField 中处理键的文本值、索引或路径转换。 将 KT()表达式传递给 annotate() 方法,该方法使用提供的 KT() 表达式注释 QuerySet 中的每个对象。

提示

要学习;了解有关 KT() 表达式和 annotate() 方法的更多信息,请参阅 Django 文档中的以下资源:

以下示例使用 annotate()KT() 创建新的 score 键,用于存储 imdb.rating 嵌套字段值。 然后,代码按 score 值降序对 sample_mflix.movies集合中的每个文档进行排序:

from django.db.models.fields.json import KT
Movie.objects.annotate(score=KT("imdb__rating")).all().order_by("-score")
<QuerySet [<Movie: No Tomorrow>, <Movie: The Deposit>, <Movie: Man Down>,
<Movie: Convenience>, <Movie: Scouts Guide to the Zombie Apocalypse>,
<Movie: Another World>, <Movie: The Danish Girl>, <Movie: Ad Inexplorata>,
<Movie: Landet som icke èr>, <Movie: The Ghost and the Whale>,
<Movie: Coming to Terms>, <Movie: La nao capitana>, <Movie: All Eyes and Ears>,
<Movie: Catching the Sun>, <Movie: Manhattan Romance>, <Movie: Anomalisa>,
<Movie: Outliving Emily>, <Movie: Mary Loss of Soul>,
<Movie: The Childhood of a Leader>, <Movie: Krot na more>,
'...(remaining elements truncated)...']>

您可以使用 pk 查找快捷方式来查询主键, MongoDB将其存储为 ObjectId 值。

以下示例将查询 sample_mflix.movies集合主键为 ObjectId("573a1394f29313caabce0d37") 的文档:

from bson import ObjectId
Movie.objects.get(pk=ObjectId("573a1394f29313caabce0d37"))
// Your ObjectId values might differ
<Movie: Vertigo>

表示 sample_mflix.movies集合的Movie 模型使用 id字段作为其主键。 以下示例使用 id字段构造与上述代码相同的查询:

from bson import ObjectId
Movie.objects.get(id=ObjectId("573a1394f29313caabce0d37"))

要学习;了解如何使用 MongoDB 的聚合管道语法运行原始数据库查询,请参阅执行原始数据库查询指南。

要学习;了解如何执行其他QuerySet 操作,请参阅执行增删改查操作指南。

要学习;了解有关 Django 查询的更多信息,请参阅 Django 文档中的“进行查询”。

后退

增删改查操作