Docs 菜单

持久化配置

在本指南中,您可以学习;了解Mongoid 如何在数据库和集合中持久保存数据。 持久性配置是指控制 Mongoid 如何在MongoDB中存储数据的设置。这包括存储模型类文档的客户端、数据库和集合,以及其他配置选项,例如读取和写入偏好。 本指南提供的方法和示例可用于访问权限和更新模型类的持久性配置。

注意

术语“客户端”是指在 mongoid.yml文件的 clients 下定义的托管配置。 大多数应用程序使用名为 default 的单个客户端。

默认情况下,Mongoid 将文档存储在一个集合中,该集合的名称是其代表类名的复数形式。 在以下示例中,对于 Restaurant 类,相应的集合名为 restaurants。 对于 Person 类,相应的集合名为 people

class Restaurant
include Mongoid::Document
end
class Person
include Mongoid::Document
end

但是,默认的复数规则并不总是有效。 示例,假设您的模型名为 Rey。 该单词在西班牙语中的复数形式是 reyes,但默认集合名称是 reys

您可以通过调用 ActiveSupport::Inflector::Inflections.plural实例方法并传递类名的单数和复数形式,为模型类创建新的复数规则。以下示例将 reyes 指定为 rey 的复数:

ActiveSupport::Inflector.inflections do |inflect|
inflect.plural("rey", "reyes")
end

因此,Mongoid 将 Rey 模型类文档存储在 reyes集合中。

注意

BSON文档结构

当 Mongoid 将文档存储在数据库中时,它会将Ruby对象序列化为具有以下结构的BSON文档:

{
"_id" : ObjectId("4d3ed089fb60ab534684b7e9"),
"title" : "Sir",
"name" : {
"_id" : ObjectId("4d3ed089fb60ab534684b7ff"),
"first_name" : "Durran"
},
"addresses" : [
{
"_id" : ObjectId("4d3ed089fb60ab534684b7e0"),
"city" : "Berlin",
"country" : "Deutschland"
}
]
}

每个模型类都包含以下方法,可用于检索有关 Mongoid 将模型持久化的位置的信息:

  • client_name:检索客户端名称

  • database_name:检索数据库名称

  • collection_name:检索集合名称

以下示例展示如何检索和打印保留 Band 类文档的客户端名称、数据库和集合:

puts Band.client_name
puts Band.database_name
puts Band.collection_name
default
my_bands
bands

Mongoid 提供模型级和运行时选项来自定义持久性配置。 以下部分介绍了这些选项。

假设您要将模型的文档存储在一个集合中,该集合的名称与模型类名称的复数形式不同。 您可以使用 store_in 宏更改 Mongoid 存储模型文档的集合、数据库或客户端。 以下示例展示了如何使用 store_in 宏在名为 analytics 的客户端端中将 Person 类中的文档存储在 other数据库中名为 citizens 的集合中:

class Person
include Mongoid::Document
store_in collection: "citizens", database: "other", client: "analytics"
end

store_in 宏还可以接受Lambda函数。 如果要使用不能使用常量字符串的值定义持久性上下文,这非常有用。

您可能希望在多租户应用程序中使用此模式,其中多个用户股票对应用程序的共同访问权限。 通过使用Lambda,您可以根据当前线程的本地信息定义持久性上下文,以便用户无法访问权限彼此的数据。

以下示例将文档存储在由线程局部变量确定的数据库中:

class Band
include Mongoid::Document
store_in database: ->{ Thread.current[:database] }
end

您可以对模型类或实例使用 with 方法,以便在运行时更改一群组操作的模型持久性配置。

对模型类或实例调用 with 方法,并传递定义持久性上下文的选项。 您可以通过两种方式调用 with 方法:

  • with(context, options)contextMongoid::PersistenceContext 的实例,options 是表示可自定义选项设立的哈希。

  • with(options)options 是一个哈希,表示一设立可自定义的选项。

然后,使用区块定义要在指定上下文中执行的操作。 您定义的上下文仅在区块中的代码运行时存在。

默认情况下,Mongoid 会将 Band 类的文档存储在名为 bands 的集合中。 以下代码示例使用 with 方法临时使用不同的客户端、数据库和集合对 Band 类的文档执行操作:

class Band
include Mongoid::Document
field :name, type: String
field :likes, type: Integer
end
# Creates document in 'bands' collection in 'music-non-stop' database within
# default cluster
Band.with(database: "music-non-stop") do |band_class|
band_class.create(name: "Medusa and the Polyps")
end
# Deletes all documents in 'artists' collection within default database
Band.with(collection: "artists") do |band_class|
band_class.delete_all
end
band = Band.new(name: "Japanese Breakfast")
# Perform operations on tertiary cluster
band.with(client: :tertiary) do |band_object|
band_object.save!
band.save!
end

注意

定义客户端

在前面的示例中,您必须在 mongoid.yml文件的 clients 下定义 tertiary集群。

重要

块作用域

您必须使用区块调用 with 方法。 这是因为 Mongoid 使用您传递给该方法的选项在背景创建新客户端。 区块定义了此客户端的范围,以便可以关闭客户端并释放其资源。

您还可以向 with 方法传递读取或写入操作的配置选项。 这些配置仅应用于指定的操作类型。

以下示例使用 with 方法指定对区块内的所有读取操作使用节点从节点(secondary node from replica set)。

Band.with(read: {mode: :secondary}) do
Band.count
# This write operation runs in the
# new persistence context, but is
# not affected by the read preference.
Band.create(name: "Metallica")
end

注意

确保上下文的一致性

当您在一个上下文中执行操作时,Mongoid 不会自动在不同的上下文中执行相同的操作。 示例,如果将 Band 模型文档插入到 artists集合中,则同一文档不会插入到 bands集合中。

在本节前面的示例中,您仅在区块的范围内更改了持久性上下文。 您可以使用 Mongoid 在全局范围内定义程序中所有操作都使用的自定义持久性上下文。 这样,您就可以在运行时更改所有操作的持久性上下文,而无需重复调用 with 方法。

您可以使用以下方法在程序中全局定义持久性上下文:

  • Mongoid.override_client:Mongoid 在指定客户端上执行所有操作。

  • Mongoid.override_database:Mongoid 对指定数据库执行所有操作。

在以下代码示例中,应用程序将不同区域设置的信息存储在不同的数据库中。 代码展示了如何使用 Mongoid.override_database 方法根据区域设置在全局设立持久性区域设置:

class BandsController < ApplicationController
before_action :switch_database
after_action :reset_database
private
def switch_database
I18n.locale = params[:locale] || I18n.default_locale
Mongoid.override_database("my_db_name_#{I18n.locale}")
end
def reset_database
Mongoid.override_database(nil)
end
end

在前面的示例中,Mongoid 在此线程上在由区域设置设置确定的备用数据库上执行所有其他操作。 由于 after_action 宏将覆盖选项设置为 nil,因此,在持久性配置不变的情况下,后续请求将使用默认配置。

您可以使用 mongo_clientcollection 类方法访问权限模型或文档实例的客户端或集合:

Band.mongo_client
band.mongo_client
Band.collection
band.collection

使用这些方法时,您还可以通过调用with 方法来设立运行时持久性选项,这与运行时持久性选项部分中的示例类似。

以下代码示例访问 Band 模型类使用的客户端。 然后,它使用客户端上的 with 方法写入music数据库,将 w写入选项设置为 0 以不需要写入确认。

Band.mongo_client.with(write: { w: 0 }, database: "music") do |client|
client[:artists].find(...)
end

您可以使用 with 方法覆盖集合上的 :read:write 选项。 以下示例演示如何使用 with 方法将 w写入选项设立为 0

Band.collection.with(write: { w: 0 }) do |collection|
collection[:artists].find(...)
end

有关本指南中提到的方法的更多信息,请参阅以下API文档: