RoR ActiveRecord and MongoDB

282 views
Skip to first unread message

Geir Magnusson

unread,
Mar 16, 2009, 8:45:56 PM3/16/09
to mongod...@googlegroups.com
From the 10gen blog :

In addition to our driver for Ruby, we've created a connection adapter
for Ruby on Rails, so you can easily use MongoDB via ActiveRecord
from within your Rails application.

You can use MongoDB either

* alone as the sole data store for your application
* with a RDBMS as a companion persistence technology

Using it as a companion technology, you can add MongoDB to
applications, both new and existing, where you need to store data for
which the relational model doesn't work well - large binary objects,
documents of varied "schema", etc, all with the ease of the
ActiveRecord API that you already know (and may even love).

Give it a try and let us know what you think!

geir


Ray Dookie

unread,
Mar 16, 2009, 8:47:04 PM3/16/09
to mongod...@googlegroups.com
lovely

Jim Mulholland

unread,
Apr 13, 2009, 10:05:02 AM4/13/09
to mongodb-user
We are testing out MongoDB with an existing Rails app. We decided to
go with the MongoRecord Ruby adapter because it was simpler to
separate out our MySQL connection setup from our MongoDB connections.

Are you able to connect to both a MySQL DB and a MongoDB at the same
time with the ActiveRecord adapter?

Also, with ActiveRecord, can you have child models (i.e has_many x)
that are not their own collection like you can with MongoRecord?


On Mar 16, 7:45 pm, Geir Magnusson <g...@10gen.com> wrote:
>  From the 10gen blog :
>
> In addition to our driver forRuby, we've created a connection adapter  
> forRubyon Rails, so you can easily use MongoDB via ActiveRecord  

Michael Dirolf

unread,
Apr 13, 2009, 12:25:15 PM4/13/09
to mongod...@googlegroups.com
inline:

On Apr 13, 2009, at 10:05 AM, Jim Mulholland wrote:

>
> We are testing out MongoDB with an existing Rails app. We decided to
> go with the MongoRecord Ruby adapter because it was simpler to
> separate out our MySQL connection setup from our MongoDB connections.
>
> Are you able to connect to both a MySQL DB and a MongoDB at the same
> time with the ActiveRecord adapter?

have you tried something like this yet?

http://schf.uc.org/articles/2006/12/06/multiple-concurrent-database-connections-with-activerecord

> Also, with ActiveRecord, can you have child models (i.e has_many x)
> that are not their own collection like you can with MongoRecord?

afaik this isn't supported. but i'm not too familiar with ActiveRecord
and the Mongo adaptor so i'm still poking around - i'll let you know
if i see a way to do this.

Jim Menard

unread,
Apr 13, 2009, 1:01:59 PM4/13/09
to mongod...@googlegroups.com
On Mon, Apr 13, 2009 at 12:25 PM, Michael Dirolf <mi...@10gen.com> wrote:
>
> inline:
>
> On Apr 13, 2009, at 10:05 AM, Jim Mulholland wrote:
>
>>
>> We are testing out MongoDB with an existing Rails app.  We decided to
>> go with the MongoRecord Ruby adapter because it was simpler to
>> separate out our MySQL connection setup from our MongoDB connections.
>>
>> Are you able to connect to both a MySQL DB and a MongoDB at the same
>> time with the ActiveRecord adapter?
>
> have you tried something like this yet?
>
> http://schf.uc.org/articles/2006/12/06/multiple-concurrent-database-connections-with-activerecord
>
>> Also, with ActiveRecord, can you have child models (i.e has_many x)
>> that are not their own collection like you can with MongoRecord?
>
> afaik this isn't supported. but i'm not too familiar with ActiveRecord
> and the Mongo adaptor so i'm still poking around - i'll let you know
> if i see a way to do this.

You should be able to set a per-class connection. ActiveRecord supports this.

Jim
--
Jim Menard, ji...@io.com, jim.m...@gmail.com
http://www.io.com/~jimm/

Michael Dirolf

unread,
Apr 13, 2009, 1:21:59 PM4/13/09
to mongod...@googlegroups.com
Yup - see the above link if you need an example.

With regards to your second question, it seems like this is a
MongoRecord specific idiom (support for Subobject instances). Since
most databases don't support inline objects it doesn't seem like there
is an ActiveRecord idiom for doing the same thing.

Jim Mulholland

unread,
Apr 13, 2009, 1:46:09 PM4/13/09
to mongodb-user
Thanks for the link. Should be very helpful.

That is what I figured regarding inline objects. Thanks for checking.

On Apr 13, 12:21 pm, Michael Dirolf <m...@10gen.com> wrote:
> On Apr 13, 2009, at 1:01 PM, Jim Menard wrote:
>
>
>
>
>
> > On Mon, Apr 13, 2009 at 12:25 PM, Michael Dirolf <m...@10gen.com>  
> > wrote:
>
> >> inline:
>
> >> On Apr 13, 2009, at 10:05 AM, Jim Mulholland wrote:
>
> >>> We are testing out MongoDB with an existing Rails app.  We decided  
> >>> to
> >>> go with the MongoRecord Ruby adapter because it was simpler to
> >>> separate out our MySQL connection setup from our MongoDB  
> >>> connections.
>
> >>> Are you able to connect to both a MySQL DB and a MongoDB at the same
> >>> time with the ActiveRecord adapter?
>
> >> have you tried something like this yet?
>
> >>http://schf.uc.org/articles/2006/12/06/multiple-concurrent-database-c...
>
> >>> Also, with ActiveRecord, can you have child models (i.e has_many x)
> >>> that are not their own collection like you can with MongoRecord?
>
> >> afaik this isn't supported. but i'm not too familiar with  
> >> ActiveRecord
> >> and the Mongo adaptor so i'm still poking around - i'll let you know
> >> if i see a way to do this.
>
> > You should be able to set a per-class connection. ActiveRecord  
> > supports this.
>
> Yup - see the above link if you need an example.
>
> With regards to your second question, it seems like this is a  
> MongoRecord specific idiom (support for Subobject instances). Since  
> most databases don't support inline objects it doesn't seem like there  
> is an ActiveRecord idiom for doing the same thing.
>
> > Jim
> > --
> > Jim Menard, j...@io.com, jim.men...@gmail.com
> >http://www.io.com/~jimm/

h_basin

unread,
Jun 5, 2009, 4:11:23 PM6/5/09
to mongodb-user
Jim, have you solved this?

No luck for me so far.

I have in my database.yml
===========
development:
adapter: mysql
database: awesome_database

foo:
adapter: mongo
database: foos

in Foo.rb model
===========
class Foo < ActiveRecord::Base

establish_connection :foos

end

> Foo.connection.instance_eval {@config[:database]}
ArgumentError: wrong number of arguments (1 for 0)
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:223:in
`mongo_connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:223:in `send'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:223:in
`new_connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:245:in
`checkout_new_connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:188:in `checkout'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:184:in `loop'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:184:in `checkout'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/
ruby/1.8/monitor.rb:242:in `synchronize'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:183:in `checkout'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:98:in `connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_pool.rb:326:in
`retrieve_connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_specification.rb:123:in
`retrieve_connection'
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.2/lib/active_record/
connection_adapters/abstract/connection_specification.rb:115:in
`connection'
from (irb):1



On Apr 13, 10:46 am, Jim Mulholland <j...@squeejee.com> wrote:
> Thanks for the link.  Should be very helpful.
>
> That is what I figured regarding inline objects.  Thanks for checking.
>
> On Apr 13, 12:21 pm, Michael Dirolf <m...@10gen.com> wrote:
>
> > On Apr 13, 2009, at 1:01 PM, Jim Menard wrote:
>
> > > On Mon, Apr 13, 2009 at 12:25 PM, Michael Dirolf <m...@10gen.com>  
> > > wrote:
>
> > >> inline:
>
> > >> On Apr 13, 2009, at 10:05 AM, Jim Mulholland wrote:
>
> > >>> We are testing out MongoDB with an existingRailsapp.  We decided  

Jim Mulholland

unread,
Jun 5, 2009, 5:33:19 PM6/5/09
to mongodb-user
I never went back to the ActiveRecord adapter. We've been using the
MongoRecord adapter to connect to Mongo objects and it has worked
great so far.

class Person < MongoRecord::Base
...
...
end

h_basin

unread,
Jun 6, 2009, 12:11:59 PM6/6/09
to mongodb-user
Thank you. Works now.

Martin Streicher

unread,
Jul 4, 2009, 5:56:16 PM7/4/09
to mongodb-user
A few questions about mixing Mongo's AR adapter and traditional MySQL
AR adapter:

1/ How does one manage migrations for Mongo? Not at all?

2/ How does one bootstrap Mongo AR? Do I simply let it read the
schema.rb that the MySQL AR migrations produce? Or do I have to
provide a separate migration to describe those models that I want to
store in Mongo?

The link referenced in this thread is missing, so I cannot read it.

Martin Streicher

unread,
Jul 4, 2009, 7:52:08 PM7/4/09
to mongodb-user

I got a little further. By default, I use the MongoDB. I can now
create and save that model in the Mongo db.

However, I have another model that I want to connect to MySQL. Using
establish_connection leaves the connection pointing to Mongo. So now
both models save in Mongo.


On Jul 4, 5:56 pm, Martin Streicher <martin.streic...@gmail.com>
wrote:

Martin Streicher

unread,
Jul 4, 2009, 11:29:14 PM7/4/09
to mongodb-user
Ah. The method mongo_connection in vendor/plugins/mongo_record/lib/
active_record/connection_adapters/mongo_adapter.rb is empty. Until
this adapter is completed, the per-class connection stuff won't work
for Mongo.

I've started an implementation of the method. I have it going as far
as select() now before it dies. I'll have to look at the documentation
for the Mongo driver to complete the adapter for ActiveRecord.

Martin

John Nunemaker

unread,
Jul 5, 2009, 9:49:08 AM7/5/09
to mongod...@googlegroups.com
You could also use MongoMapper with Rails. It supports a connection
per model.

http://github.com/jnunemaker/mongomapper



On Jul 4, 2009, at 11:29 PM, Martin Streicher <martin.s...@gmail.com

Martin Streicher

unread,
Jul 5, 2009, 12:57:27 PM7/5/09
to mongodb-user
If I use MM, can I do things like :has_many from other models?

Ideally, I would like some guidance on AR and Mongo to try and
implement the concrete adapter for AR. I am happy to make the fork
available once finished.

Any takers for assisting me -- I may need to ask questions along the
way.


On Jul 5, 9:49 am, John Nunemaker <nunema...@gmail.com> wrote:
> You could also use MongoMapper with Rails. It supports a connection  
> per model.
>
> http://github.com/jnunemaker/mongomapper
>
> On Jul 4, 2009, at 11:29 PM, Martin Streicher <martin.streic...@gmail.com

John Nunemaker

unread,
Jul 5, 2009, 3:01:59 PM7/5/09
to mongod...@googlegroups.com
You can't do many from other models unless they are embedded docs. I
haven't figured out the best way to relate docs across collections.
DBRefs are great but you can't query against them. I'll probably end
up using dbrefs for belongs_to/parent relationships and use
article_ids or something like that to store all the ids from the other
collection, if that makes sense.

Anyone from mongodb crew know if querying against dbrefs is in the
future? I can explain what I'm thinking if I haven't made myself clear.

Eliot Horowitz

unread,
Jul 5, 2009, 8:21:29 PM7/5/09
to mongod...@googlegroups.com
Do you mean querying on the _id, or on attributes on the referenced document?

John Nunemaker

unread,
Jul 6, 2009, 12:26:39 AM7/6/09
to mongod...@googlegroups.com
I was talking attributes on the referenced document.



On Jul 5, 2009, at 8:21 PM, Eliot Horowitz <elioth...@gmail.com>
wrote:

Eliot Horowitz

unread,
Jul 6, 2009, 7:11:55 AM7/6/09
to mongod...@googlegroups.com
Its not on our short list, but if a lot of people need it we could do it.

John Nunemaker

unread,
Jul 7, 2009, 11:51:34 PM7/7/09
to mongod...@googlegroups.com
Well, I'm working around it using foreign key type lookups but it
feels wrong. I'm just thinking if you had users and articles as top
level collections and wanted to have a key articles on user that was
an array of dbrefs, it would be nice to be able to query inside of
them instead of pulling them all out first, say to match all articles
by the user published this year.

I can see 3 options for the has_many type relationship in my limited
experience with mongo.

1) Articles have user_id which gets set. You can then query based on
that. Pretty much same as relational.
2) User has key article_ids that is an array of article ids. If you
want to query articles from a user, always make sure that the Article
criteria is scoped to those id's with $in or something.
3) User has array of dbrefs that point to articles. If you want a
subset of those articles, say all published this year, you'd have to
pull out all of them and check at the language level or pull out all
ids and then scope Article query similar to #2.

Some kind of map/reduce thing could work if it was performant or maybe
db.eval could do something? I haven't looked at the eval or group
stuff much yet.

I'd be curious what you all would recommend or have found to work in
this situation. I could also see a 4th option that maybe combined a
few of the above and just picked which to use based on how you needed
to get access to the objects at that particular time.

I could be missing something so please let me know if there is a way
to do something like I'm talking about already in a relatively
efficient manner.

Wouter

unread,
Jul 8, 2009, 10:48:29 AM7/8/09
to mongodb-user
With option 1:
+ you need to create an extra index (user_id)
+ you db will remain consistent (if you remove an article, there won't
be any references to it)

With option 2:
+ your list of article_IDs might be incorrect. If an article is
deleted, the ID in article_IDs won't be removed (you will have to do
that yourself)
+ If you want to update the array of article IDs, it is difficult to
do that atomic. To add an article, you would need $push - which only
allows you to add one value at a time. Moreover, there is no atomic
way to remove a value from the array. There is no, so to say, $pull
modifier. (I requested both features at http://jira.mongodb.org/browse/SERVER-132
and http://jira.mongodb.org/browse/SERVER-130).

With option 3:
+ I don't think DBrefs are suitable for ORM/ActiveRecord related
things. A DBref stores collection and ID, but if you're looking at
something like users' articles, you already know what collection
you're looking at. And as you already said, you can't query on the
data.

I personally think - for ORM/ActiveRecord type of behavior - option 1
is best suitable. It does require an extra index, but you won't have
any concurrency issues. Option 2 might become suitable if they decide
to build/improve $push/$pushAll/$pull.

(I'm not working with Ruby, but I'm building a PHP based ORM library
for MongoDB, so I thought about the same things :-))
> > On Mon, Jul 6, 2009 at 12:26 AM, John Nunemaker<nunema...@gmail.com>  
> > wrote:
>
> >> I was talking attributes on the referenced document.
>
> >> On Jul 5, 2009, at 8:21 PM, Eliot Horowitz <eliothorow...@gmail.com>
> >> wrote:
>
> >>> Do you mean querying on the _id, or on attributes on the referenced
> >>> document?
>
> >>> On Sun, Jul 5, 2009 at 3:01 PM, John Nunemaker<nunema...@gmail.com>

John Nunemaker

unread,
Jul 8, 2009, 10:57:41 AM7/8/09
to mongod...@googlegroups.com
Cool. Glad to here my thoughts are in the right place. I have
callbacks and such built into MongoMapper so most of the removing of
id's and such should work and be fairly stable but I'm going to stick
with 1 for now unless anyone else comes up with better way.

Hunter Nield - syndeolabs/g2ix

unread,
Jul 9, 2009, 1:47:18 AM7/9/09
to mongodb-user
Interesting discussion guys.

Associations was something I was wondering about when I looked at AR
Mongo and MongoMapper. The docs on DBRef seem a little light on
details.

It sounds like we can fall back to our familiar relational DB ways
unless something new comes about.

On Jul 9, 12:57 am, John Nunemaker <nunema...@gmail.com> wrote:
> Cool. Glad to here my thoughts are in the right place. I have  
> callbacks and such built into MongoMapper so most of the removing of  
> id's and such should work and be fairly stable but I'm going to stick  
> with 1 for now unless anyone else comes up with better way.
>
> On Jul 8, 2009, at 10:48 AM, Wouter wrote:
>
>
>
>
>
> > With option 1:
> > + you need to create an extra index (user_id)
> > + you db will remain consistent (if you remove an article, there won't
> > be any references to it)
>
> > With option 2:
> > + your list of article_IDs might be incorrect. If an article is
> > deleted, the ID in article_IDs won't be removed (you will have to do
> > that yourself)
> > + If you want to update the array of article IDs, it is difficult to
> > do that atomic. To add an article, you would need $push - which only
> > allows you to add one value at a time. Moreover, there is no atomic
> > way to remove a value from the array. There is no, so to say, $pull
> > modifier. (I requested both features athttp://jira.mongodb.org/browse/SERVER-132
> > andhttp://jira.mongodb.org/browse/SERVER-130).

Wouter

unread,
Jul 9, 2009, 10:10:42 AM7/9/09
to mongodb-user
> It sounds like we can fall back to our familiar relational DB ways
> unless something new comes about.

They're not that different. Everything in mongo is key => value:

some_key => array( collection_name => _ID )

collection_name => _ID / parent_collection_name => _ID

collection_name => array( _ID, _ID.. etc)

The first one actually is a DBref, the rest are all 'relational'
examples, but as you can see, they don't really differ that much. The
only thing is that with DBref, the driver understands the format and
you can do $mongoDB->getDBref($ref), but that's just a wrapper for
$mongoDB->select_collection(name)->findOne( _id ). For the 2nd and 3rd
example, you can easily write the code yourself :-)

On 9 jul, 07:47, "Hunter Nield - syndeolabs/g2ix"
Reply all
Reply to author
Forward
0 new messages