Я решил подобные проблемы, создав модель в «середине», например «ItemReference». MongoDB - это хранилище документов, а не реляционная база данных, поэтому при необходимости можно хранить дублирующую информацию.MongoDB имеет возможность хранить встроенные документы, поэтому мы собираемся использовать эту замечательную функцию.
ItemReference содержит всю важную информацию о Item, необходимую для создания представления.Это уменьшает количество запросов на стороне представления, но увеличивает количество запросов на стороне вставки / обновления.
Дело в том, что вам нужен «составной первичный ключ», который состоит из item_id
и номера версии.
Давайте поговорим код:
Модель товара:
class Item
include Mongoid::Document
include Mongoid::Paranoia
include Mongoid::Versioning
field :title, :type => String
# create a reference
def to_reference
# create new reference, containing all crucial attributes for displaying
ItemReference.new(
:item_id => self._parent.nil? ? self.id : self._parent.id,
:version => self.version,
:title => self.title
)
end
# get a certain version of this item
def get_version(version_number)
return self if version_number == self.version
self.versions.where(:version => version_number).first
end
end
Модель набора предметов
class ItemSet
include Mongoid::Document
field :name, :type => String
embeds_many :item_references
end
Модель ItemReference
class ItemReference
include Mongoid::Document
embedded_in :item_sets
field :title, :type => String
# this points to the newest version
belongs_to :item
# get the original version
def original
self.item.get_version(self.version)
end
# update this reference to a certain version
def update_to!(new_version)
new_version = self.item.get_version(new_version)
if new_version.present?
# copy attribute, except id
self.attributes = new_version.to_reference.attributes.reject{|(k,v)| k == "_id"}
self.save
else
# version not found
false
end
end
# update to the newest version
def update_to_head!
self.update_to!(self.item.version)
end
end
Эта комбинация позволяет создавать наборы, содержащие элементы с разными версиями, и вы можете обновить определенные ItemReferences в наборе до определенной версии.
Вот пример:
first = Item.create(:title => 'Item 1')
first.title = 'Item 1.1'
first.save
myset = ItemSet.create(:title => 'My Set')
myset.item_references << first.to_reference
myset.save
first.title = 'Item 1.2'
first.save
p myset.item_references.first.title # prints Item 1.1
p myset.item_references.first.update_to_head!
p myset.item_references.first.title # prints Item 1.2
p myset.item_references.first.update_to!(1)
p myset.item_references.first.title # prints Item 1