新增功能
在此页面上
了解以下版本中的新功能:
要查看版本列表和详细的发布说明,请参阅Github上的 Mongoid 版本。
9.0 中的新功能
9.0发布包括以下新增功能、改进和修复:
Railsmdb
随着 Mongoid v9.0 的发布, railsmdb
是一个用于创建、更新、管理和维护 Rails 应用程序的命令行实用程序,现已正式发布。
railsmdb
使通过Ruby on Rails 开发者已经熟悉的通用生成器可以更轻松地命令行使用MongoDB 。
示例,您可以使用railsmdb
为新的 Mongoid 模型生成存根:
bin/railsmdb generate model person
这将在app/models/person.rb
处创建一个新模型:
class Person include Mongoid::Document include Mongoid::Timestamp end
您可以指定模型的字段:
bin/railsmdb generate model person name:string birth:date
class Person include Mongoid::Document include Mongoid::Timestamp field :name, type: String field :birth, type: Date end
您可以通过传递--parent
选项来指示生成器将新模型设为另一个模型的子类:
bin/railsmdb generate model student --parent=person
class Student < Person include Mongoid::Timestamp end
如果您需要将模型存储在不同于从模型名称推断的集合中,则可以指定 --collection
:
bin/railsmdb generate model course --collection=classes
class Course include Mongoid::Document include Mongoid::Timestamp store_in collection: 'classes' end
有关更多信息,请参阅Github上的 mongoid-railsmdb存储库。
移除对Ruby 2.6 和 JRuby 9.3 的支持
Mongoid v9.0 需要Ruby 2.7 或更高版本或 JRuby 9.4。 不支持早期的Ruby和 JRuby 版本。
删除了对 Rails 5 的支持
Mongoid v9.0 需要 Rails 6.0 或更高版本。 不支持早期的 Rails 版本。
删除已弃用的类 Mongoid::Errors::InvalidStorageParent
已弃用的Mongoid::Errors::InvalidStorageParent
类已被删除。
around_*
嵌入式文档的回调被忽略
Mongoid v8.x 及更早版本允许用户为嵌入式文档定义 around_*
回调。 从 v9.0 开始, 这些回调将被忽略,不会被执行。 如果定义了此类回调,则控制台将打印警告。
如果要恢复旧行为,可以在应用程序中将Mongoid.around_embedded_document_callbacks
设立为 true。
注意
不建议为嵌入式文档启用around_*
回调,因为当文档具有许多嵌入式文档时,可能会导致SystemStackError
异常。 请参阅 MONGOID-5658 了解更多详情。
for_js
方法已弃用
for_js
方法已弃用,并将在 Mongoid v10.0 中删除。
删除已弃用的选项
重大更改:Mongoid v 中删除了以下配置选项。9.0请确保您已从应用应用中删除对这些内容的所有引用。 如果您在升级之前使用的是 config.load_defaults 8.1
,则不会出现任何行为变化。 有关每个选项的含义,请参阅早期的发布说明。
:use_activesupport_time_zone
:broken_aggregables
:broken_alias_handling
:broken_and
:broken_scoping
:broken_updates
:compare_time_by_ms
:legacy_attributes
:legacy_pluck_distinct
:legacy_triple_equals
:object_id_as_json_oid
:overwrite_chained_operators
此外,已删除对 config.load_defaults
版本 v7.5 及更早版本的支持(您必须至少使用版本 v8.0。)
删除已弃用的功能
重大更改:以下已弃用的功能现已删除:
Mongoid::QueryCache
模块已被删除。 请将 1-for-1 的所有用法替换为Mongo::QueryCache
。 方法Mongoid::QueryCache#clear_cache
应替换为Mongo::QueryCache#clear
。 所有其他方法和子模块的名称相同。Object#blank_criteria?
方法已删除(之前已弃用)。Document#as_json :compact
选项已删除。 请改为对返回的Hash
对象调用`#compact
。已弃用的
Mongoid::Errors::InvalidStorageParent
类已被删除。
touch
方法清除更改状态
在 Mongoid v8.x 及更早版本中,touch
方法使模型处于更改状态:
# v8.x behaviour band = Band.create! band.touch band.changed? # => true band.changes # => {"updated_at"=>[2023-01-30 13:12:57.477191135 UTC, 2023-01-30 13:13:11.482975646 UTC]}
从 v9.0 开始, Mongoid 现在可以在使用 touch
方法后正确清除变更状态。
# v9.0 behavior band = Band.create! band.touch band.changed? # => false band.changes # => {}
Rails 控制台的沙盒模式
Mongoid 现在支持 Rails 控制台沙盒模式。 如果 Rails 控制台使用 --sandbox
标志启动,则 Mongoid 会在打开控制台之前在 :default
客户端上启动ACID 事务。 此ACID 事务不会提交。 因此,使用 :default
客户端在控制台中执行的所有命令都不会保留在数据库中。
注意
如果使用 default 以外的任何其他客户端在沙盒模式下执行命令,这些更改将照常保留。
新事务API
Mongoid 9.0 引入了受 Active Record 启发的新事务API :
Band.transaction do Band.create(title: 'Led Zeppelin') end band = Band.create(title: 'Deep Purple') band.transaction do band.active = false band.save! end
嵌入式文档始终使用父持久性上下文
Mongoid v8.x 及更早版本允许用户为嵌入式文档指定持久性上下文(使用 store_in
宏)。 在 Mongoid v9.0 对于嵌入式文档,这些设置将被忽略。 嵌入式文档现在始终使用其父文档的持久性上下文。
支持将原始值传递到查询中
在执行查询时,现在可以使用 Mongoid::RawValue
包装器类跳过 Mongoid 的类型强制逻辑。 当数据库中的传统数据的类型与字段定义不同时,这非常有用。
class Person include Mongoid::Document field :age, type: Integer end # Query for the string "42", not the integer 42 Person.where(age: Mongoid::RawValue("42"))
访问查询投影中省略的字段时引发 AttributeNotLoaded
错误
现在,当尝试访问模型实例上的字段时,如果在加载实例时使用only
或without
查询投影方法排除了该字段,Mongoid 现在会引发Mongoid::Errors::AttributeNotLoaded
错误。
Band.only(:name).first.label #=> raises Mongoid::Errors::AttributeNotLoaded Band.without(:label).first.label = 'Sub Pop Records' #=> raises Mongoid::Errors::AttributeNotLoaded
在早期的 Mongoid 版本中,相同的条件会引发ActiveModel::MissingAttributeError
。 请检查您的代码中是否有此类的任何特定于 Mongoid 的用法,并将其更改为Mongoid::Errors::AttributeNotLoaded
。 另外请注意, AttributeNotLoaded
会继承自Mongoid::Errors::MongoidError
,而ActiveModel::MissingAttributeError
不会。
在查询中使用配置的时区将 Date
类型转换为 Time
当使用日期值查询时间字段时,Mongoid 现在可以正确地考虑Time.zone
来执行类型转换。
class Magazine include Mongoid::Document field :published_at, type: Time end Time.zone = 'Asia/Tokyo' Magazine.gte(published_at: Date.parse('2022-09-26')) #=> will return all results on or after Sept 26th, 2022 # at 0:00 in Asia/Tokyo time zone.
在以前的 Mongoid 版本中,上述代码会忽略 Time.zone
(无论现在已删除的 :use_activesupport_time_zone
设置如何),并始终使用系统时区域来执行类型转换。
请注意,在以前的 Mongoid 版本中,在持久性操作期间将 Date
类型转换为 Time
已经正确使用时区域。
针对嵌入式文档的 touch
方法可以正确处理 touch: false
选项
当对embedded_in
关系设立touch: false
选项时,对嵌入式子文档调用touch
方法将不会对其父文档调用touch
。
class Address include Mongoid::Document include Mongoid::Timestamps embedded_in :mall, touch: false end class Mall include Mongoid::Document include Mongoid::Timestamps embeds_many :addresses end mall = Mall.create! address = mall.addresses.create! address.touch #=> updates address.updated_at but not mall.updated_at
此外, touch
方法已经过优化,即使在使用多个级别的嵌套嵌入式文档时,也可对每个父文档执行一个持久性操作。
embedded_in
关联默认为 touch: true
更新嵌入式子文档现在将自动触及父文档,除非您在该关系上显式设立touch: false
:
class Address include Mongoid::Document include Mongoid::Timestamps embedded_in :mall, touch: false end
对于所有其他关联,默认仍为touch: false
。
已翻转 upsert
中 :replace
选项的默认值
Mongoid v8.1 向 upsert
方法添加了 :replace
选项。 此选项用于指定是否应更新或替换现有文档。
Mongoid v9.0 将此标志的默认从 true
翻转为 false
。 这意味着,默认,Mongoid v9.0 更新现有文档,而不是替换它。
强制执行的 _id
字段的不变性
在 Mongoid v9.0 之前, 修改 _id
字段的行为会不一致,具体取决于文档是顶层文档还是嵌入式文档,以及更新的执行方式。 在 v9.0 中, 现在,如果文档之前已持久保存,则更改 _id
字段现在会在保存文档时引发异常。
Mongoid 9.0还引入了一个新的功能标志immutable_ids
,默认为true
。
Mongoid::Config.immutable_ids = true
当设立为 false
时,将恢复较早的不一致行为。
支持索引选项的字段别名
已添加对在index
宏的以下选项中使用别名字段名称的支持: partial_filter_expression
、 weights
、 wildcard_projection
。
class Person include Mongoid::Document field :a, as: :age index({ age: 1 }, { partial_filter_expression: { age: { '$gte' => 20 } }) end
注意
索引选项中字段名称别名的扩展(例如partial_filter_expression
)是根据MongoDB 服务器 6.0的行为执行的。 未来的服务器版本可能会改变对这些选项的解释方式,Mongoid 的功能可能不支持此类更改。
BSON 5 和 BSON::Decimal128
字段
当BSON 4 或更早版本存在时,声明为 BSON::Decimal128
的任何字段都将返回 BSON::Decimal128
值。 但是,当BSON 5 存在时,声明为 BSON::Decimal128
的任何字段都将默认返回 BigDecimal
值。
class Model include Mongoid::Document field :decimal_field, type: BSON::Decimal128 end # under BSON <= 4 Model.first.decimal_field.class #=> BSON::Decimal128 # under BSON >= 5 Model.first.decimal_field.class #=> BigDecimal
如果您需要具有BSON 5 的字面 BSON::Decimal128
值,您可以指示 Mongoid 支持字面 BSON::Decimal128
字段:
Model.first.decimal_field.class #=> BigDecimal Mongoid.allow_bson5_decimal128 = true Model.first.decimal_field.class #=> BSON::Decimal128
注意
allow_bson5_decimal128
选项仅在 BSON 5及更高版本下有效。 BSON 4及更早版本完全忽略该设置。
MongoDB Atlas的搜索索引管理
连接到MongoDB Atlas时,Mongoid 现在支持创建和删除搜索索引。 您可以通过 Mongoid::SearchIndexable
API以编程方式执行此操作:
class SearchablePerson include Mongoid::Document search_index { ... } # define the search index here end # create the declared search indexes; this returns immediately, but the # search indexes may take several minutes before they are available. SearchablePerson.create_search_indexes # query the available search indexes SearchablePerson.search_indexes.each do |index| # ... end # remove all search indexes from the model's collection SearchablePerson.remove_search_indexes
如果未连接到MongoDB Atlas,则会忽略搜索索引定义。 尝试创建、枚举或删除搜索索引将导致错误。
为了方便起见,还提供了 rake 任务:
# create search indexes for all models; waits for indexes to be created # and shows progress on the terminal. $ rake mongoid:db:create_search_indexes # as above, but returns immediately and lets the indexes be created in the # background $ rake WAIT_FOR_SEARCH_INDEXES=0 mongoid:db:create_search_indexes # removes search indexes from all models $ rake mongoid:db:remove_search_indexes
删除 Time.configured
Time.configured
返回包装已配置时区域的时间对象,或标准Ruby Time
类。 这样,即使没有配置时区域,您也可以查询时间值。
现在,如果您打算对时间值执行任何操作(包括在文档中使用时间戳),Mongoid 都要求您设置时区。 对Time.configured
的任何使用都必须替换为Time.zone
。
# before: puts Time.configured.now # after: puts Time.zone.now # or, better for finding the current Time specifically: puts Time.current
如果不设立时区域,您将在代码中看到与nil
值相关的错误。 如果您使用的是 Rails,则默认时区域已设立为 UTC。 如果您不使用 Rails,则可以在程序启动时设立时区域,如下所示:
Time.zone = 'UTC'
这会将时区域设立为 UTC。 您可以通过运行以下命令来查看所有可用的时区域名称:
$ ruby -ractive_support/values/time_zone \ -e 'puts ActiveSupport::TimeZone::MAPPING.keys'
记录记住创建的持久性上下文
考虑以下代码:
record = Model.with(collection: 'other_collection') { Model.first } record.update(field: 'value')
在 Mongoid v9.0 之前,上述代码无法以静默方式执行更新,因为记录不会记住存储选项(此处为模型的备用集合规范)。 因此,该记录将从 other_collection
加载,但在更新时会尝试在模型的默认集合中查找并更新该文档。 为此,您必须为每次更新显式指定集合。
从 Mongoid v9.0 开始, 在显式存储选项下创建或加载的记录,将记住这些选项(包括命名客户端、不同数据库或不同集合)。
如果您需要旧版(v9.0 之前的版本) 行为,您可以使用以下标志启用它:
Mongoid.legacy_persistence_context_behavior = true
在 Mongoid v9.0 中,此标志默认为 false。