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

时间:2022-09-02 02:41:04

I'm using rails 3, and began my application with ActiveRecord. Now, I have many models, and the relations are starting to get complicated, and some could be more simply expressed with a Document-Oriented structure, so I'd like to try migrating to MongoDB and use Mongoid.

我正在使用rails 3,并使用ActiveRecord启动了我的应用程序。现在,我有了很多模型,并且关系开始变得复杂起来,有些可以用面向文档的结构简单地表达出来,所以我想尝试迁移到MongoDB并使用Mongoid。

I've always heard that you didn't have to eitheer use all MongoDB or nothing, but that you could use the two in parallel while migrating. I don't see how to go about this from the docs though.

我总是听说你不必使用所有MongoDB或者什么都不用,但是你可以在迁移的时候同时使用这两个。但是我不知道如何从文档中了解这些。

For example, I have:

例如,我有:

class User < ActiveRecord::Base
   has_many :items
   has_many :products, :through => :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

I'd like to ideally begin by replacing my Item activerecord model with a Mongoid document, so my items are stored in MongoDB, and my Users and Products can stay in my SQL DB

我希望在理想的情况下,开始用Mongoid文档替换我的项目activerecord模型,这样我的项目就存储在MongoDB中,我的用户和产品可以保存在我的SQL DB中。

Thing is, I don't see how to do this. Am I going about this the right way?

问题是,我不知道怎么做。我这样做对吗?

Perhaps another alternative is to keep a base AR Item

也许另一种选择是保留一个基本的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

Thanks!

谢谢!

4 个解决方案

#1


10  

I don't see any reason why you couldn't have both ActiveRecord and Mongoid models in the same application. That being said, I'm almost certain that you'll run into issues if you try to create relationships between your ActiveRecord and Mongoid models.

我不明白为什么不能在同一个应用程序中同时拥有ActiveRecord和Mongoid模型。也就是说,如果您尝试在您的ActiveRecord和Mongoid模型之间创建关系,我几乎可以肯定您会遇到问题。

If your ActiveRecord models are heavily inter-related, but better suited to a document structure, then I would suggest just biting the bullet and converting them all to Mongoid documents. I had to do this recently on a (large-ish) project, and it's significantly less stressful than you would think.

如果您的ActiveRecord模型与文档结构密切相关,但更适合文档结构,那么我建议您直接将它们转换为Mongoid文档。我最近在一个(大的)项目上做了这个,它比你想象的压力要小得多。

If you have good unit tests for your models, then it should be a total snap. If you don't - write your unit tests first, make sure they pass with ActiveRecord and then start migrating things over to Mongoid.

如果你对你的模型有好的单元测试,那么它应该是完全容易的。如果您不编写单元测试,请确保它们通过了ActiveRecord,然后开始将代码迁移到Mongoid。

#2


14  

What I did was just mock the relationship with methods in each the AR model and the Mongoid model like so.

我所做的只是模仿每个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

Of course you won't have all the AR methods on VisitSession Mongoid model but you'll at least be able to mock the relationship between the two fairly well.

当然,您不会拥有关于VisitSession Mongoid模型的所有AR方法,但您至少可以很好地模拟这两个模型之间的关系。

Hope this helps.

希望这个有帮助。

#3


0  

... just for tracking purpose, I'd like to add something I just found out on this field:

…为了便于跟踪,我想补充一些我刚刚在这个领域发现的东西:

DRY up your SQL+NoSQL Rails projects

使您的SQL+NoSQL Rails项目枯竭

#4


0  

i created a module for spoofing the relation in active record models.

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

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

In my SQL table, I name my mongo relations using the convention mongo_XXX_id, instead of XXX_id

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

I also namespace all my mongo models under Mongo::

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

in my active record model

在我的活动记录模型中

class Foo < ActiveRecord::Base
    belongs_to_mongo :XXX
end

which allows

它允许

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

or

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

#1


10  

I don't see any reason why you couldn't have both ActiveRecord and Mongoid models in the same application. That being said, I'm almost certain that you'll run into issues if you try to create relationships between your ActiveRecord and Mongoid models.

我不明白为什么不能在同一个应用程序中同时拥有ActiveRecord和Mongoid模型。也就是说,如果您尝试在您的ActiveRecord和Mongoid模型之间创建关系,我几乎可以肯定您会遇到问题。

If your ActiveRecord models are heavily inter-related, but better suited to a document structure, then I would suggest just biting the bullet and converting them all to Mongoid documents. I had to do this recently on a (large-ish) project, and it's significantly less stressful than you would think.

如果您的ActiveRecord模型与文档结构密切相关,但更适合文档结构,那么我建议您直接将它们转换为Mongoid文档。我最近在一个(大的)项目上做了这个,它比你想象的压力要小得多。

If you have good unit tests for your models, then it should be a total snap. If you don't - write your unit tests first, make sure they pass with ActiveRecord and then start migrating things over to Mongoid.

如果你对你的模型有好的单元测试,那么它应该是完全容易的。如果您不编写单元测试,请确保它们通过了ActiveRecord,然后开始将代码迁移到Mongoid。

#2


14  

What I did was just mock the relationship with methods in each the AR model and the Mongoid model like so.

我所做的只是模仿每个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

Of course you won't have all the AR methods on VisitSession Mongoid model but you'll at least be able to mock the relationship between the two fairly well.

当然,您不会拥有关于VisitSession Mongoid模型的所有AR方法,但您至少可以很好地模拟这两个模型之间的关系。

Hope this helps.

希望这个有帮助。

#3


0  

... just for tracking purpose, I'd like to add something I just found out on this field:

…为了便于跟踪,我想补充一些我刚刚在这个领域发现的东西:

DRY up your SQL+NoSQL Rails projects

使您的SQL+NoSQL Rails项目枯竭

#4


0  

i created a module for spoofing the relation in active record models.

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

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

In my SQL table, I name my mongo relations using the convention mongo_XXX_id, instead of XXX_id

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

I also namespace all my mongo models under Mongo::

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

in my active record model

在我的活动记录模型中

class Foo < ActiveRecord::Base
    belongs_to_mongo :XXX
end

which allows

它允许

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

or

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