如何在Rails 3中并行使用Mongoid和ActiveRecord?

我正在使用rails 3,并使用ActiveRecord开始我的应用程序。 现在,我有很多模型,关系开始变得复杂,有些可以用Document-Oriented结构更简单地表达,所以我想尝试迁移到MongoDB并使用Mongoid。

我一直听说你没有必须使用所有MongoDB或者没有任何东西,但你可以在迁移时并行使用这两个。 我不知道如何从文档中解决这个问题。

例如,我有:

class User  :items end class Product < ActiveRecord::Base has_many :items end class Item < ActiveRecord::Base belongs_to :user belongs_to :product # alot of data that fits a hierarchical document-oriented structure end 

我想在理想情况下首先用Mongoid文档替换我的Item activerecord模型,这样我的项目就存储在MongoDB中,我的UsersProducts可以保留在我的SQL DB中

事情是,我不知道该怎么做。 我是以正确的方式来做这件事的吗?

也许另一种选择是保留基础AR项目

 class Item < ActiveRecord::Base has_one :mongodb_item ?? # I know this is wrong end class MongodbItem include Mongoid::Document belongs_to AR_Item ??? # I know this is also wrong end 

谢谢!

我没有看到为什么你不能在同一个应用程序中同时拥有ActiveRecord和Mongoid模型的原因。 话虽如此,我几乎可以肯定,如果你试图在ActiveRecord和Mongoid模型之间建立关系,你会遇到问题。

如果您的ActiveRecord模型是相互关联的,但更适合文档结构,那么我建议只是咬住子弹并将它们全部转换为Mongoid文档。 我最近不得不在一个(大型)项目上做到这一点,它的压力比你想象的要小得多。

如果您对模型进行了良好的unit testing,那么它应该是完全快速的。 如果你不这样做 – 首先编写你的unit testing,确保它们通过ActiveRecord,然后开始将东西迁移到Mongoid。

我所做的只是模仿每个AR模型和Mongoid模型中的方法的关系。

 # visit_session.rb class VisitSession include Mongoid::Document include Mongoid::Timestamps field :user_id, type: Integer index({user_id: 1},{name: :user_id_index}) # Mock a belongs_to relationship with User model def user User.find(self.user_id) end end # user.rb class User < ActiveRecord::Base # Mock a has_many relationship with VisitSession Mongoid model def visit_sessions VisitSession.where(user_id: self.id) end end 

当然,你不会在VisitSession Mongoid模型上拥有所有的AR方法,但你至少能够很好地模拟两者之间的关系。

希望这可以帮助。

…仅仅为了追踪目的,我想在这个领域添加我刚刚发现的东西:

干掉你的SQL + NoSQL Rails项目

我创建了一个欺骗活动记录模型中关系的模块。

 module MongoRelations def belongs_to_mongo(name, options = {}) id_name = "mongo_#{name}_id".to_sym mongo_model = options[:through] || "Mongo::#{name.to_s.camelize}".constantize define_method(name) do id = send(id_name) mongo_model.find(id) if id.present? end define_method("#{name}=") do |value| send("#{id_name}=".to_sym, value.try(:id).to_s) end end end 

在我的SQL表中,我使用约定mongo_XXX_id命名我的mongo关系,而不是XXX_id

我还将所有mongo模型命名为Mongo ::

在我的活跃记录模型中

 class Foo < ActiveRecord::Base belongs_to_mongo :XXX end 

这使得

 Foo.new.XXX = Mongo.find('123') Foo.XXX 

要么

 Foo.new.XXX_id = '123' Foo.XXX