你将如何深入克隆MongoDB中的文档(mongoid)
我尝试过这样的事情;
original = Car.find(old_id)
@car = original.clone
@car._id = BSON::ObjectId.new
但是之后我对这些值的反序列化产生了问题。
如何使用除_id?
之外的所有文档属性进行深度克隆编辑: 在遵循Zachary的示例后,我遇到了一些针对重复文档的自定义序列化类的问题。
class OptionHash
include Mongoid::Fields::Serializable
# Convert the keys from Strings to Symbols
def deserialize(object)
object.symbolize_keys!
end
# Convert values into Booleans
def serialize(object)
object.each do |key, value|
object[key] = Boolean::MAPPINGS[value]
end
end
对于重复文档,对象为零。 Car.find(old_id).attributes确实不包含自定义序列化的字段,为什么会这样,我该如何包含它呢?
答案 0 :(得分:7)
您无需为此调用.clone,您可以使用attributes
中的原始数据。例如,如果找到一个,则下面的方法/示例将在整个文档中给出新的ID。
def reset_ids(attributes)
attributes.each do |key, value|
if key == "_id" and value.is_a?(BSON::ObjectId)
attributes[key] = BSON::ObjectId.new
elsif value.is_a?(Hash) or value.is_a?(Array)
attributes[key] = reset_ids(value)
end
end
attributes
end
original = Car.find(old_id)
car_copy = Car.new(reset_ids(original.attributes))
你现在有了Car的副本。这是低效的,因为它必须通过记录的整个哈希来确定嵌入文档中是否存在任何嵌入文档。如果您知道它的结构,最好自己重置结构,例如,如果您将部件嵌入汽车,那么您可以这样做:
original = Car.find(old_id)
car_copy = Car.new(original.attributes)
car_copy._id = BSON::ObjectId.new
car_copy.parts.each {|p| p._id = BSON::ObjectId.new}
这比仅进行通用重置更有效率。
答案 1 :(得分:0)
如果您有本地化字段,则必须使用Car.instantiate
,因此代码为
def reset_ids(attributes)
attributes.each do |key, value|
if key == "_id" && value.is_a?(Moped::BSON::ObjectId)
attributes[key] = Moped::BSON::ObjectId.new
elsif value.is_a?(Hash) || value.is_a?(Array)
attributes[key] = reset_ids(value)
end
end
attributes
end
car_original = Car.find(id)
car_copy = Car.instantiate(reset_ids(car_original.attributes))
car_copy.insert
这个解决方案不是很干净但我找不到更好的。