Using MongoDb with CakePHP

NoSQL datasources are becoming a bigger part of our everyday life as web developers. If you haven’t heard about it before, MongoDB is a SQL free database built in C++. Its a fast, scalable, document oriented datasource that feels like a great middle ground between traditional RDBMS, and key value stores like Memcached. MongoDB supports things like indexes and dynamic queries, which make it feel slightly less alien when coming from a traditional RDBMS. I originally intended to sit down and start writing a Mongo datasource only to find that Yasushi Ichikaway had totally beat me to it, and written a great datasource. So instead, I’ll write about how you can get up and running with MongoDB.

Install MongoDB and the PHP extension

For me this was as simple as using homebrew and running brew install mongodb. There are also packages available via Macports, and probably many other package managers. If your operating system doesn’t include a way to compile code, you can download a package . Next up was to install the PHP extension. For me this was another simple sudo pecl install mongo. I used launchd to start up the server, and keep it running.

Download and setup the mongodb datasource

As previously mentioned, Yasushi Ichikaway has done a great job with the mongoDB datasource. I cloned the repository into my plugins directory. I then added a database connection to my database.php

Show Plain Text
  1.  
  2. var $mongo = array(
  3.     'datasource' => 'mongodb.mongodbSource',
  4.     'database' => 'my_test',
  5.     'host' => 'localhost',
  6.     'port' => 27017
  7. );
  8.  

After I had made a connection, I connected a model to the datasource, and made a simple controller/view to save some records. My model looked like:

Show Plain Text
  1. class Note extends AppModel {
  2.     var $name = 'Note';
  3.     var $primaryKey = '_id';
  4.     var $useDbConfig = 'mongo';
  5.  
  6.     function schema() {
  7.         $this->_schema = array(
  8.             '_id' => array('type' => 'integer', 'primary' => true, 'length' => 40),
  9.             'title' => array('type' => 'string'),
  10.             'body' => array('type' => 'text'),
  11.             'numbered' => array('type' => 'integer'),
  12.         );
  13.         return $this->_schema;
  14.     }
  15. }

I did need to have var $useTable = false; before the first record was inserted. But after that, I was able to remove it. I figured this was due to mongo creating collections as they are written. My controller and view were basic and looked exactly like the ones bake makes. Outside of some hiccups with a missing $columns property on the datasource when trying to save datetime columns, things went really smoothly.

I think MongoDB is a really interesting data storage solution. Its use of javascript and json/bson internally is very attractive and interesting. The PHP interface is also very well designed and easy to use. I haven’t had much time to play with all the various NoSQL databases, but MongoDb is definitely a good looking choice from my short time with it.

Comments

MongoDB seems to be a really good option.

But I haven’t seen any more complex example, with use of embedded objects or relationships with that datasource.

Somebody has tried ?

Sebastien Charrier on 29/3/10

Thank you for using and explaining MongoDB Datasource.
Now, I release ver0.2

Properties of each model become little simple. primaryKey(_id) is automatically set. using mongSchema property insted of _schema.
You don’t need to set “var $useTable = false;” if there is no collection(Table).

Here is new sample model for ver0.2

class Note extends AppModel {
    var $name = 'Note';
    var $useDbConfig = 'mongo';
	var $mongoSchema = array(
            'title' => array('type' => 'string'),
            'body' => array('type' => 'text'),
            'numbered' => array('type' => 'integer'),
        );

}

ichikaway on 29/3/10

Sebastien: While MongoDB doesn’t support associations or joins out of the box, you could emulate them at the datasource level.

Ichikaway: Awesome, looks like a nice set of improvements :D

mark story on 29/3/10

Hi,

I am using Cake 1.2.6 and have some difficulty using ver0.2 when using $mongoScheme, it looks like cake does not interpret column type integer properly when inserting new records.

I tried to insert record with integer values, but when I query back using mongo console (db.mytable.find()), the supposed-to-be-integer value is display as string

I traced the Cake model.php source, and at line 1034, there is $this->scheme() call, which I believe there should be a function schema() inside the model as posted in this page

I am new to Cake framework, but I like to use mongoDB for my application. can someone help out.

thanks

fiqar on 15/4/10

Hi again,
please ignore my previous comment.

Now it seems that cakephp does not typecast well the integer format. so the question is, how to properly insert integer (or float) values to mongoDB from cakephp, currently, all are inserted as string values

fiqar on 15/4/10

One thing I feel is not mentioned clearly about the Mongo DSO is that is DOES support deep document hierarchies (= nested arrays) and not only the simple datatypes listed in the source code (string, integer…).

It looks to me like any “datatype” can be an array and the schema will be ignored (i.e. not treated as a string or something). For clarity one can apparently even just set the datatype to array just for clarity.

I did not see this mentioned anywhere in your post or in the docs for the dso. For me and my purposes that is a big deal and no mention of it meant no support in my mind. I am very happy I created a model and ran some tests though. :)

Martin Westin on 16/4/10

what about apache cassandra ( http://cassandra.apache.org/ )?

r0mk1n on 3/5/10

I fail to understand the advantages of using a NoSQL database with CakePHP. In any case, one does not use the SQL syntax directly, since the interaction with the database is hidden behind the CakePHP layer. So, what does this change?

Andrea on 6/5/10

MongoDB looks pretty much amazing! It’s time to get my hand dirty.

Veselin Todorov on 26/5/10

Nice work from Yasushi Ichikaway.

I have two questions:

Which is the best way to store images, movies in MongoDB? Write a own Datasource (for Gridfs) or extend the MDS?

And can i specify in the mongoschema types like MongoBinData?

thanks in advance

Mika on 17/6/10

The update method of the datasource is in error here.
Instead of upgrading, it inserts a new record.

Rafael Queiroz on 27/7/10

Can not connect to servers with user and password

Rafael Queiroz on 27/7/10

@Rafael: Make sure you have echo $form->hidden(’_id’); in your edit/update form.

Octavian on 28/7/10

Hello.

I`ve little problem. I tried many times to connect mongodb datasource with cakephp. But only what i get is this: ConnectionManager::loadDataSource – Unable to import DataSource class mongodb.mongodbSource [CORE\cake_1.3\cake\libs\model\connection_manager.php, line 185]

mongodb_source.php datasource I insert in app/models/datasources/. Where is the problem?

Artis on 24/8/10

@Artis – You need to clone the repository into your plugins directory

Voidet on 10/9/10

It has to look like:

cakephp/app/plugins/mongodb/models/datasources/mongodb_source.php

Fakie on 17/9/10

I see the ensureIndex() method defined on the MongodbSource class. But how do I call/use it?
Thank you.

David on 25/9/10

I really love the MongoDB and with cake it’s looks quite more beatifull now =). I hope cakephp will have native nosql drivers in next releases (and with auto schemes like sql maybe).

For now this driver looks awesome, thanks for all efforts.

PS: Cake Bake ignores “plugin” datasources. I never inspect bake mechanism just noticed and saying in addition.
PHP Fatal error: Class ‘Mongo’ not found in /cake/1.3/cake/libs/model/connection_manager.php on line 114

Furkan Tunalı on 29/9/10

Thanks.

I always have wanted to define my schema in my model exactly like this does. And I secretly always wanted to use Mongo anyway!

Matt

Matt Kaufman on 9/10/10

< prev123

Have your say:

*
* You can use Textile markup, but be reasonable