修改查询结果
Overview
在本指南中,您可以学习;了解如何自定义 Mongoid 返回查询结果的方式。 MongoDB允许您执行以下操作来修改结果的显示方式:
样本数据
本指南中的示例使用 Band
模型,该模型表示乐队或音乐群组。 每个部分的 Band
模型的定义可能不同,以演示不同的查询功能。 某些部分还使用 Manager
模型(表示给定乐队的管理人员)或 Tour
模型(表示给定乐队的现场表演)。
返回指定字段
在MongoDB中,投影是指定要从结果中包含或排除的字段的进程。Mongoid 提供以下操作符来项目字段:
only
:指定要包含的字段without
:指定要排除的字段
包含字段
only
方法只从数据库中检索指定字段。
以下代码仅返回 members
字段值为 4
的文档中的 name
字段:
Band.where(members: 4).only(:name)
注意
_id字段
在MongoDB中,即使您没有显式包含 _id
字段也会包含在结果中。
如果尝试引用尚未加载的属性,Mongoid 会引发 Mongoid::Errors::AttributeNotLoaded
错误。
您还可以使用 only
方法包含嵌入式文档中的字段。
假设 Band
模型嵌入了多个 Tour
对象。 您可以项目Tour
模型中的字段,例如 year
,如以下代码所示:
bands = Band.only(:name, 'tours.year')
然后,您可以从返回的文档访问权限嵌入式字段:
# Returns the first Tour object from # the first Band in the results bands.first.tours.first
您可以将引用关联的字段传递给 only
方法,但在加载嵌入式对象时会忽略投影。 Mongoid 加载引用关联的所有字段。 示例,当您访问权限前面代码中所示的嵌入式 Tour
对象时,Mongoid 返回完整的对象,而不仅仅是 year
字段。
注意
如果您连接到运行MongoDB 4.4 或更高版本的部署,则无法在同一查询中的投影中指定关联及其字段。
如果文档包含 has_one
或 has_and_belongs_to_many
关联,并且您希望 Mongoid 在调用 only
方法时加载这些关联,则必须在属性列表中包含带有外键的字段。
在以下示例中,Band
和 Manager
模型具有 has_and_belongs_to_many
关联:
class Band include Mongoid::Document field :name, type: String has_and_belongs_to_many :managers end class Manager include Mongoid::Document has_and_belongs_to_many :bands end
以下代码演示了如果包含 manager_ids
字段, Mongoid 如何加载关联的 Manager
对象:
# Returns null Band.where(name: 'Astral Projection').only(:name).first.managers # Returns the first Manager object Band.where(name: 'Astral Projection').only(:name, :manager_ids).first.managers
排除字段
您可以使用 without
方法从结果中明确排除字段。
以下代码从返回的 Band
对象中排除 year
字段:
Band.where(members: 4).without(:year)
重要
_id字段
Mongoid 需要_id
字段来执行各种操作,因此您不能从结果中排除 _id
字段或id
别名。如果将 _id
或 id
传递给 without
方法,Mongoid 会将其忽略。
对结果进行排序
您可以使用 order
和 order_by
方法指定 Mongoid 返回文档的顺序。
这些方法接受一个哈希值,该哈希值指示按哪些字段对文档进行排序,以及对每个字段使用升序还是降序。
可以使用整数、符号或字符串指定排序方向。 为了一致性,我们建议在整个应用程序中使用相同的排序语法。 以下列表提供了每种语法,并显示了如何对 name
和 year
字段进行排序:
整数
1
(升序)和-1
(降序)示例:
Band.order(name: 1, year: -1)
符号
:asc
和:desc
示例:
Band.order(name: :asc, year: :desc)
字符串
"asc"
和"desc"
示例:
Band.order_by(name: "asc", year: "desc")
order
方法还接受以下排序规范:
二元素数组的数组:
字符串
示例:
Band.order([['name', 'asc'], ['year', 'desc']])
符号
示例:
Band.order([[:name, :asc], [:year, :desc]])
asc
以及针对符号的desc
方法示例:
Band.order(:name.asc, :year.desc)
SQL语法
示例:
Band.order('name asc', 'year desc')
提示
除了使用 order
或 order_by
之外,您还可以使用 asc
和 desc
方法来指定排序顺序:
Band.asc('name').desc('year')
当您链式排序规范时,第一次调用定义第一个排序顺序,最后一个调用定义应用先前排序后的最后一个排序顺序。
对结果进行分页
Mongoid 提供了可在 Criteria
对象上使用的 limit
、skip
和 batch_size
分页方法。 以下部分介绍了如何使用这些操作符。
限制结果数量
您可以使用 limit
方法来限制 Mongoid 返回的结果数量。
以下代码最多检索 5
个文档:
Band.limit(5)
注意
或者,可以使用 take
方法从数据库中检索指定数量的文档:
Band.take(5)
跳过结果
您可以使用 skip
方法或其别名 offset
跳过指定数量的结果。
如果将 limit
调用链接到 skip
,则在跳过文档后应用限制,如以下示例所示:
Band.skip(2).limit(5) # Skips the first two results and returns # the following five results
以下代码在返回结果时跳过前 3
个文档:
Band.skip(3) # Equivalent Band.offset(3)
生成结果批次
执行大型查询以及使用Criteria#each
等枚举器方法迭代查询结果时,Mongoid 会自动使用MongoDB getMore 命令分批加载结果。默认批处理大小为 1000
,但您可以使用 batch_size
方法设立不同的值。
以下代码将批处理大小设置为 500
:
Band.batch_size(500)