更新Mongoid中的哈希类型属性

时间:2011-08-22 16:06:03

标签: ruby-on-rails-3 mongoid

我想在Mongoid中更新哈希类型属性。

这是一个例子

class A
 include Mongoid::Document

 field :hash_field, :type => Hash
end

现在让我们假设已有填充数据,例如

A.last.hash_field 
=> {:a => [1]}

现在我想更新哈希并希望最终输出为{:a => [1,2]}

我试过

a = A.last
a.hash_field[:a] << 2
a.save
=> true

a.hash_field
=> {:a => [1,2]}

但是当我查询为

A.last.hash_field
=> {:a => [1]}

谢谢意味着它实际上没有更新任何东西 现在我如何根据需要更新?

提前致谢!

3 个答案:

答案 0 :(得分:3)

这可能与Mongoid浅拷贝哈希的方式有关。如果是这样,那么这可能会有助http://spin.atomicobject.com/2011/04/13/mongoid-hash-field-types-watch-out/

注意:我没有根据您的具体情况测试解决方案

答案 1 :(得分:2)

这与Mongoid如何优化字段更新有关。具体来说,由于您正在更新哈希字段内的元素,因此字段“观察者”不会获取内部更新,因为字段自身的值(指向哈希)保持不变。

我采用的解决方案是为我想存储的任何复杂对象(例如Hash)提供通用序列化器。这是一个好处,它是一个通用的解决方案,只是工作。缺点是它会阻止您使用内置的Mongo操作查询哈希的内部字段以及一些额外的处理时间。

如果没有进一步的说明,这就是解决方案。 首先,为新的Mongoid自定义类型添加此定义。

class CompressedObject
  include Mongoid::Fields::Serializable

  def deserialize(serialized_object)
    return unless serialized_object
    decompressed_string = Zlib::Inflate.inflate(serialized_object.to_s)
    Marshal.load(decompressed_string)
  end

  def serialize(object)
    return unless object
    obj_string = Marshal.dump(object)
    compressed_string = Zlib::Deflate.deflate(obj_string, Zlib::BEST_SPEED)
    BSON::Binary.new(compressed_string)
  end
end

其次,在Model(包括Mongoid::Document)中,使用新类型,如下所示:

  field :my_hash_field, :type => CompressedObject

现在,您可以使用该字段执行任何操作,并且每次都可以正确序列化。

答案 2 :(得分:1)

我的问题有点不同,但你可能会从我解决它的方式中受益。 我的mongo文档中有一个哈希映射数组字段,这是最终处理它的表单:

<% @import_file_import_configuration.fieldz.each do |fld| %>
  <tr>
    <td>
      <input type="number" name="import_file_import_configuration[fieldz][][index]" value='<%=fld["index"]%>'/>
    </td><td>
      <input type="textbox" name="import_file_import_configuration[fieldz][][name]" value='<%=fld["name"]%>'/>
    </td>
  </tr>
<% end %>

我在我的数组中存储了每个2个键(“index”和“name”)的映射。 这就是我的文档定义:

class Import::FileImportConfiguration
  field :file_name, type: String
  field :model, type: String
  field :fieldz, type: Array, default: []
end