Docs 菜单
Docs 主页
/ / /
Mongoid
/

持久化配置

在此页面上

  • 文档存储
  • 持久性上下文属性
  • 自定义分析器
  • 模型级持久性选项
  • 运行时持久性选项
  • 客户端和集合访问

默认情况下,Mongoid 将文档存储在集合中,该集合是类名的复数形式。 对于以下 Person类,存储文档的集合将命名为people

class Person
include Mongoid::Document
end

模型类名称不能以“s”结尾,因为它将被视为单词的复数形式。 示例,“Status”将被视为“Statu”的复数形式,这会导致一些已知问题。

这是ActiveSupport::Inflector#classify的限制,Mongoid 使用 将文件名和集合名称转换为类名。 您可以通过为模型类指定自定义变形规则来克服这个问题。 例如,以下代码将处理名为Status的模型。

ActiveSupport::Inflector.inflections do |inflect|
inflect.singular("status", "status")
end

如果您希望模型文档的集合在其他地方持久保留,则可以在类级别更改它们。 您还可以更改模型持久保存的数据库和客户端的默认值。

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

store_in宏还可以采用 lambda — 常见的情况是多租户应用程序。

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

当文档存储在数据库中时,Ruby对象将被序列化为BSON ,并具有如下结构:

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

Mongoid 在模型类上提供了client_namedatabase_namecollection_name方法,以确定用于持久性的客户端、数据库和集合名称:

Band.client_name
# => :default
Band.database_name
# => "mongoid"
Band.collection_name
# => :bands

在某些情况下,您可能希望将文档持久保存到不同于默认值的不同源,或者使用不同于默认值的不同选项。 Mongoid 对此提供运行时支持以及基于每个模型的支持。

您可以在每个模型的基础上,将名称、不同的数据库或不同的客户端存储在自定义集合中。 默认,以下示例会将 Band 类存储到名为“music”的数据库中名为“artists”的集合中,客户端为“分析”。

请注意,为client选项提供的值必须在 mongoid.yml 中的clients下配置。

class Band
include Mongoid::Document
store_in collection: "artists", database: "music", client: "analytics"
end

如果没有提供store_in宏,Mongoid 会将模型存储在默认客户端默认数据库中名为“bands”的集合中。

通过在模型类或实例上使用with方法,可以更改用于一群组操作的持久性的客户端、数据库和集合以及任何MongoDB客户端选项:

Band.with(database: "music-non-stop") do |klass|
klass.create(...)
band = Band.first
Band.create(...)
end
Band.with(collection: "artists") do |klass|
klass.delete_all
Band.delete_all
end
band.with(client: :tertiary) do |band_object|
band_object.save!
band.save!
end

with方法创建临时持久性上下文和用于在上下文中操作的MongoDB客户端。 在该区块的持续时间内,调用with的模型类或实例上的持久性上下文将更改为临时持久性上下文。 为方便起见,调用with的模型类或实例将生成为区块。

临时持久性上下文适用于查询和写入。

跨不同持久化上下文执行持久化操作时应谨慎。 示例,如果将文档保存在临时持久性上下文中,则它可能不存在于默认持久性上下文中,从而导致后续更新失败:

band = Band.new(name: "Scuba")
band.with(collection: "artists") do |band_object|
band_object.save!
end
# This will not save - updates the collection "bands" which does not have
# the Scuba band
band.update_attribute(likes: 1000)
# This will update the document.
band.with(collection: "artists") do |band_object|
band_object.update_attribute(likes: 1000)
end

从 Mongoid 6.0开始,必须始终使用区块调用with方法,并且临时持久性上下文仅在区块期间存在。 这是因为会在幕后创建一个新客户端,并将选项传递给with 。 为了确保此客户端已关闭并释放其相关资源,必须明确定义可以使用此客户端的范围。

如果您想在运行时切换所有操作的持久性上下文,但又不想在所有代码中使用,Mongoid 可以在全局范围内作为客户端和数据库级别执行此操作。 实现此目的的方法是Mongoid.override_clientMongoid.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

在上面的示例中,所有持久性操作都将存储在该线程上所有剩余操作的备用数据库中。 这就是为什么 after 请求将覆盖设置回零 - 它确保没有本地参数的后续请求使用默认选项。

持久性上下文适用于读取和写入操作。 例如,可以按如下方式执行从节点读取:

Band.with(read: {mode: :secondary}) do
Band.count
end

如果要下拉到驾驶员级别执行操作,可以从模型或文档实例中获取mongo客户端或集合:

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

从这里开始,您还可以使用客户端的#with获得相同的运行时持久性选项:

client = Band.mongo_client.with(write: { w: 0 }, database: "musik")
client[:artists].find(...)

您还可以使用集合#with覆盖集合上的 :read 或 : 写入选项:

collection_w_0 = Band.collection.with(write: { w: 0 })
collection_w_0[:artists].find(...)

后退

Map-Reduce