我找不到任何博客文章或文档讨论这个问题。它们(嵌入式文档和散列数据类型)都非常相似。两者的优势和局限性是什么?
考虑我的模式设计:
class HistoryTracker
include ::Mongoid::Document
include ::Mongoid::Timestamps
field :modifier, type: Hash, default: {}
field :original, type: Hash, default: {}
field :modified, type: Hash, default: {}
field :changeset, type: Hash, default: {}
end
我应该在这个HistoryTracker类中创建几个嵌入式文档吗?还是直接用它?索引呢?
Mongoid在数据库级以几乎相同的方式存储嵌入文档和哈希属性。使用monid时,在模型中声明字段是很正常的,所以如果你有一个嵌套结构,创建一个嵌入文档是很正常的。因为MongoDB是无模式的,mongoid需要你声明字段,以便在ActiveRecord所做的相同类型的API中呈现它们。但是对于某些用例,Hash属性可以提供更多的灵活性。这种灵活性的缺点是,您受限于Hash API,因此您无法获得自动生成的属性方法,并且您无法以通常在模型类中所做的方式封装业务逻辑。
作为一个例子,假设您有一个Questionnaire模型,您需要在其中存储包含许多问答对的许多部分。如果系统的一个关键要求是管理员能够设置新的部分和问题,那么您就不容易将答案建模为包含每个问题显式字段的常规嵌入式文档。对于这种事情,哈希可能更有意义。
我不知道您的具体要求是什么,但作为一个粗略的指导,我想说,当您使用固定的模式坚持嵌入文档时,但是当您需要一个开放式模型时,请考虑Hash属性。
对于嵌入式文档,您还可以使用属性别名,如
class Outer
include Mongoid::Document
embeds_one :inner_informative_object_with_long_name, store_as: :inn
end
class Embedded
include Mongoid::Document
attribute :vvla, as: :very_very_long_attribute, type: String
end
所以在数据库中你有短的名字(更少的内存使用),你在你的代码中使用长名字
使用哈希代替嵌入文档时遇到的问题
当Mongoid要序列化文档时,它目前不会查看嵌套的哈希值,并假设它们已经序列化了。
所以如果你想有一个像下面这样的"散列转储"
class Event
include Mongoid::Document
field :properties, type: Hash
end
则不能在属性
中使用对象class Foo
include Mongoid::DOcument
end
e = Event.new(
properties: {
some_info: Foo.new
}
}
尝试持久化以下事件将导致崩溃,因为Foo不会被序列化(尝试e.as_document
,您将看到some_info
的值不会被序列化)
对问题的参考:Github, MongoDB跟踪器