Docs 菜单
Docs 主页
/ / /
Mongoid
/ /

范围界定

在本指南中,您可以学习;了解如何在 Mongoid 模型中实现作用域。作用域提供了一种重复使用常用过滤条件的便捷方法。要学习;了解有关创建过滤条件的更多信息,请参阅指定文档查询指南。

如果您对大多数查询应用相同的条件,则可以在应用应用程序中实现作用域以减少重复代码。

命名范围是在类加载时定义的条件,由提供的名称引用。 与过滤条件类似,它们是延迟加载且可链接的。

此示例定义了一个 Band 模型,其中包括以下命名范围:

  • japanese:匹配 country字段值为 "Japan" 的文档

  • rock:匹配其中 genre字段的值包含 "rock" 的文档

class Band
include Mongoid::Document
field :country, type: String
field :genres, type: Array
scope :japanese, ->{ where(country: "Japan") }
scope :rock, ->{ where(:genres.in => [ "rock" ]) }
end

然后,您可以使用命名范围进行查询。 以下查询使用命名作用域来匹配 country字段值为 "Japan"genre字段值包括 "rock" 的文档:

Band.japanese.rock

您可以在命名范围中定义 Proc 对象和区块,以便它们接受参数并扩展功能。

此示例定义了一个包含 based_in 作用域的 Band 模型,该模型匹配 country字段值为作为参数传递的指定值的文档:

class Band
include Mongoid::Document
field :name, type: String
field :country, type: String
scope :based_in, ->(country){ where(country: country) }
end

然后,您可以使用 based_in 范围进行查询,如以下代码所示:

Band.based_in("Spain")

Mongoid 允许您定义一个作用域来隐藏现有的类方法,如以下示例所示:

class Band
include Mongoid::Document
def self.on_tour
true
end
scope :on_tour, ->{ where(on_tour: true) }
end

通过将 scope_overwrite_exception 配置选项设置为 true,您可以指示 Mongoid 在作用域覆盖现有类方法时引发错误。

要学习;了解有关此设置的更多信息,请参阅应用程序配置指南。

如果您对大多数查询应用相同的条件,则默认作用域非常有用。 通过定义默认范围,您可以将这些条件指定为使用该模型的任何查询的默认。 默认作用域返回 Criteria 对象。

要创建默认作用域,您必须在模型类上定义 default_scope 方法。

以下代码在 Band 模型上定义 default_scope 方法,以仅检索active字段值为 true 的文档:

class Band
include Mongoid::Document
field :name, type: String
field :active, type: Boolean
default_scope -> { where(active: true) }
end

然后,对 Band 模型的任何查询都会预筛选 active 值为 true 的文档。

默认范围会将新模型的字段初始化为默认范围中给定的值,默认是这些值是文字,例如布尔值或整数。

注意

字段和作用域冲突

如果在字段定义和默认域中提供默认值,则默认域中的值优先,如以下示例所示:

class Band
include Mongoid::Document
field :name, type: String
field :on_tour, type: Boolean, default: true
default_scope ->{ where(on_tour: false) }
end
# Creates a new Band instance in which "on_tour" is "false"
Band.new

我们不建议使用点表示法来引用默认作用域中的默认字段。 这可能会指示 Mongoid 在新模型中初始化意外字段。

示例,如果定义引用 tour.year字段的默认作用域,则新模型将使用字段tour.year 进行初始化,而不是使用带有包含 year字段的嵌套对象的 tour字段。

查询 时,Mongoid 会正确解释点表示法,并匹配嵌套字段具有指定值的文档。

如果在属于关联的模型上定义默认作用域,则必须重新加载关联才能重新应用作用域。 如果您更改关联中的文档值,从而在应用范围时影响其可见性,则必须执行此操作。

此示例使用以下模型:

class Label
include Mongoid::Document
field :name, type: String
embeds_many :bands
end
class Band
include Mongoid::Document
field :name, type: String
field :active, default: true
embedded_in :label
default_scope ->{ where(active: true) }
end

假设您创建一个 Label 模型,其中包含与 Band 的关联,其中 active 的值为 true。 当您将 active字段更新为 false 时,尽管默认作用域,Mongoid 仍会加载该字段。 要查看应用范围的关联中的文档,您必须调用 reload操作符。

以下代码演示了此序列:

label = Label.new(name: "Hello World Records")
band = Band.new(name: "Ghost Mountain")
label.bands.push(band)
label.bands # Displays the Band because "active" is "true"
band.update_attribute(:active, false) # Updates "active" to "false"
# Displays the "Ghost Mountain" band
label.bands # => {"_id":"...","name":"Ghost Mountain",...}
# Won't display "Ghost Mountain" band after reloading
label.reload.bands # => nil

Mongoid 将默认范围内的条件视为任何其他查询条件。 在使用 ornor 方法时,这可能会导致令人惊讶的行为。

以下示例演示了 Mongoid 如何解释对具有默认范围的模型的查询:

class Band
include Mongoid::Document
field :name
field :touring
field :member_count
default_scope ->{ where(touring: true) }
end
# Combines the condition to the default scope with "and"
Band.where(name: 'Infected Mushroom')
# Interpreted query:
# {"touring"=>true, "name"=>"Infected Mushroom"}
# Combines the first condition to the default scope with "and"
Band.where(name: 'Infected Mushroom').or(member_count: 3)
# Interpreted query:
# {"$or"=>[{"touring"=>true, "name"=>"Infected Mushroom"}, {"member_count"=>3}]}
# Combines the condition to the default scope with "or"
Band.or(member_count: 3)
# Interpreted query:
# {"$or"=>[{"touring"=>true}, {"member_count"=>3}]}

要学习;了解有关逻辑操作的更多信息,请参阅《指定查询》指南中的逻辑操作。

您可以使用 unscoped操作符指示 Mongoid 不要应用默认范围,如以下示例所示:

# Inline example
Band.unscoped.where(name: "Depeche Mode")
# Block example
Band.unscoped do
Band.where(name: "Depeche Mode")
end

您可以使用 with_scope 方法在运行时更改区块中的默认作用域。

以下模型定义了命名范围 mexican

class Band
include Mongoid::Document
field :country, type: String
field :genres, type: Array
scope :mexican, ->{ where(country: "Mexico") }
end

您可以使用 with_scope 方法在运行时将 mexican 命名作用域设立为默认作用域,如以下代码所示:

Band.with_scope(Band.mexican) do
Band.all
end

Mongoid 将返回 Criteria 对象的类方法视为作用域。 您可以使用这些类方法查询,如以下示例所示:

class Band
include Mongoid::Document
field :name, type: String
field :touring, type: Boolean, default: true
def self.touring
where(touring: true)
end
end
Band.touring

要学习;了解有关自定义 Mongoid 模型的更多信息,请参阅对数据建模指南。

后退

指定查询

在此页面上