Overview
在本指南中,您可以学习;了解如何使用 Django MongoDB后端来指定数据库查询。
您可以通过创建查询过滤来优化查询返回的文档设立。查询过滤是一个表达式,用于指定MongoDB在读取或写入操作中用于匹配文档的搜索条件。 在查询过滤中,您可以提示 Django MongoDB后端搜索与您的查询完全匹配的文档,也可以编写查询筛选器以Express更复杂的匹配条件。
查询 API
Django QuerySet
API提供了允许您检索模型对象的方法。 要运行MongoDB 数据库查询,请在模型管理器上调用 QuerySet
方法。 Manager
类处理数据库操作,并允许您通过引用 Django 模型与MongoDB数据交互。 默认情况下,Django 会向每个模型类添加一个名为 objects
的 Manager
。
将 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>]>
Retrieve One Document
要从集合中检索一份文档,请在模型管理器上调用 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)...']>
运行原始数据库查询
如果要运行Django 的查询API不支持的复杂查询,可以使用 raw_aggregate()
方法。 此方法允许您在MongoDB聚合管道中指定查询条件,并将其作为参数传递给 raw_aggregate()
。
自定义查询筛选器
您可以在查询过滤中使用字段查找来进一步优化查询条件。字段查找可让您明确正在查询的字段与要查询的值之间的关系。 使用以下语法指定字段查找:
Model.objects.filter(<field name>__<lookup type>=<value>)
您可以使用不同的查找类型执行高级查询,例如部分文本匹配、大量元素查询、正则表达式匹配以及日期时间字段的年份值匹配。
本节介绍如何通过以下方式优化查询筛选器:
使用文本匹配查找
下表描述了可用于运行包含文本值的特定匹配条件的查询的一些查找类型:
查找类型 | 说明 |
---|---|
| 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 . |
| Specifies a partial text match. You can specify a case-insensitive partial text match
by using icontains . |
| Matches field values that begin with the specified text. You can specify a case-insensitive partial text match
by using istartswith . |
| 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)...']>
使用比较查找
下表描述了可用于运行根据指定值评估字段值的查询的部分查找类型:
查找类型 | 说明 |
---|---|
| Matches field values that are greater than the
specified value. |
| Matches field values that are greater than or equal
to the specified value. |
| Matches field values that are less than the specified
value. |
| 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)...']>
组合查找
您可以通过以下方式运行使用多组匹配条件的查询:
使用
Q
对象,并用逻辑操作符分隔每个对象。要学习;了解更多信息,请参阅 Django 文档中的使用 Q 对象进行的复杂查找。
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>]>
修改查询结果
本节介绍如何通过以下方式修改查询结果:
对结果进行排序
您可以使用 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>
高级字段查询
本节介绍如何对以下字段类型运行查询:
查询 EmbeddedModelField
您可以在模型上运行查询嵌入式模型字段的操作。 要查询这些字段,请指定模型字段和每个嵌入式字段名称,并用双下划线 (__
) 分隔,直到找到要查询的字段,如以下代码所示:
Model.objects.filter(<model field>__<embedded model field>=<value>)
您还可以使用字段查找来优化嵌入式模型查询。在要查询的嵌入式模型字段之后添加查找类型,并以双下划线为前缀。
例子
此示例使用查找来查询嵌入在 Movie
模型中的 Award
模型。 此嵌入式模型表示 sample_mflix.movies
集合中的 awards
字段及其嵌套的 wins
、nominations
和 text
字段。 以下代码查询 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
您可以使用标准查询语法查询在 ArrayField
值中的数据。 Django MongoDB后端提供了用于查询 ArrayField
值的其他字段查找类型,如下表所述:
查找类型 | 说明 |
---|---|
| 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. |
| Matches fields that store a subset of the provided values.
This lookup type is the inverse of contains . |
| Matches field that store any of the provided values. |
| 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
您可以使用与查询JSONField
EmbeddedModelField 部分所示相同的语法来查询在 值中的数据。将每个字段和嵌套字段名称链接在一起,用双下划线 (__
) 分隔,直到到达要查询的字段。
以下示例查询值为 JSONField
的 imdb
字段,其嵌套 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)...']>
注释和筛选JSON数据
您可以使用 KT()
表达式来注释和过滤JSONField
值中存储的数据。 KT()
表达式允许您在 JSONField
中处理键的文本值、索引或路径转换。 将 KT()
表达式传递给 annotate()
方法,该方法使用提供的 KT()
表达式注释 QuerySet
中的每个对象。
以下示例使用 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 的聚合管道语法运行原始数据库查询,请参阅执行原始数据库查询指南。