具有嵌入式关联的深度克隆文档 [英] Deep clone document with embedded associations
问题描述
您将如何在MongoDB(蒙古包)中深度克隆文档
How would you go about deep cloning a document in MongoDB (mongoid)
我已经尝试过类似的事情
I've tried something like this;
original = Car.find(old_id)
@car = original.clone
@car._id = BSON::ObjectId.new
但是后来我反序列化了值.
But I get problems deserialization of the values afterwards.
如何使用_id以外的所有文档属性进行深层克隆?
How can I make a deep clone with all the documents attributes except the _id?
在遵循Zachary的示例之后,我对于重复文档的自定义序列化类遇到了一些问题.
After following Zachary's example I got some problems with a custom serialization class for the duplicated documents.
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
对于重复的文档,对象为nil. Car.find(old_id).attributes确实不包含带有自定义序列化的字段,为什么要这么做,以及如何包含它呢?
Object is nil for duplicated documents. Car.find(old_id).attributes indeed doesn't include the field with the custom serialization, why is that and how can I include it?
推荐答案
您无需对此调用.clone,您可以使用attributes
中的原始数据.例如,下面的方法/示例将在整个文档中找到一个新ID.
You don't need to call .clone on this, you can use the raw data from attributes
. For example the below method/example will give new ids throughout the entire document if it finds one.
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的副本.但是这效率很低,因为它必须遍历整个散列才能使记录找出在嵌入式文档中是否有任何嵌入式文档.如果您知道结构如何,最好自行重置结构,例如,如果将部件嵌入到汽车中,则可以执行以下操作:
And you now have a copy of Car. This is inefficient though as it has to go through the entire hash for the record to figure out if there are any embedded documents in an embedded document. You would be better off resetting the structure yourself if you know how it'll be, for example, if you have a parts embedded into car, then you can just do:
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}
比普通的重置要有效得多.
Which is a lot more efficient than just doing a generic reset.
这篇关于具有嵌入式关联的深度克隆文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!