embedded document vs hash datatype in mongoid

2019-06-17 05:13发布

问题:

I can't find any blog post or documentation talking about this. They both, embedded document and hash data type, are quite similar. What the benefit or limitation of each over the other?

Consider my schema design:

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

Should I create several embedded document inside this HistoryTracker class? or just use that? How about indexing?

回答1:

Mongoid stores embedded documents and Hash attributes in pretty much the same way at the database level. Its normal when working with mongoid to declare your fields in your models so if you have a nested structure its normal to create an embedded document. Because MongoDB is schema-less mongoid needs you to declare fields in order to present them in the same kind of API that ActiveRecord does. But for some use cases a Hash attribute gives you a bit more flexibility. The downside of that flexibility is that you are limited to the Hash API so you don't get auto-generated attribute methods and you can't encapsulate business logic in the way that you might normally do within a model class.

As an example, suppose you have a Questionnaire model in which you need to store many sections containing many question-answer pairs. If a key requirement of the system is for the administrator to be able to setup new sections and questions then you would not easily be able model the answers as a regular embedded document containing explicit fields for each question. For that kind of thing a Hash might make more sense.

I don't know what your specific requirements are but as a rough guide I would say that when you are working with a fixed schema stick with an embedded document, but when you need an open-ended model consider Hash attributes.



回答2:

With an embedded document you also have attribute aliases, as in

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

so in the database you have short names (much less memory used) and you use the long ones in your code.



回答3:

A problem I ran into with using Hashes instead of embedded documents

When Mongoid is about to serialize a document, it currently does not look at nested values of hashes and assumes they are already serialized.

so if you wanted to have a "Hash dump" like the following

class Event
  include Mongoid::Document
  field :properties, type: Hash
end

Then you CANNOT use objects in the properties

class Foo 
  include Mongoid::DOcument
end

e = Event.new(
  properties: {
    some_info: Foo.new
  }
}

Trying to persist the following event will cause a crash because Foo will not be serialized (try e.as_document and you'll see the value of some_info will not be serialized)

references to the issues : Github, MongoDB tracker