FallenRayne Dev One developer's random thoughts are better than nothing.

29Jan/113

Playing around with MongoDB

So I have been messing around with MongoDB now for about 2 months on a side project that I am working on. I wanted to give a run down on my thoughts about Mongo and the PHP driver for it.

Installation:

The installation of Mongo was relatively simple, mostly because I just installed it on my Ubuntu machine using the Debian package. Got it installed and running in under 20 minutes and had a interface downloaded and in place in about 10 minutes after that. The PHP driver was a simple as running

1
sudo pecl install mongo

and adding

1
extension=mongo.so

to the php.ini file. All in all the process was extremely simple and there were no major hiccups.

Documentation:

The documentation is pretty clear overall. They have some good quick start tutorials and everything is pretty easy to follow. The documentation for the PHP driver is on php.net and just as you would expect PHP documentation, not perfect but most definitely not the worst out there. There have been enough sites that explain usage though I have had some troubles here and there, but I will explain those later.

Ease of Use:

This is where things get fun. Mongo is an extremely fun database to use. The logic of how the documents are constructed just makes so much sense to me as they are essentially just JSON strings. My major passion in web development is JavaScript so this just makes things fun. I am trying to do some great stuff with the queries because I am doing live filtering on the data as the user types. I currently have four different combo boxes and two text fields that the user can type into and automatically filter the content that is displayed. I am able to do this with Mongo's great query capabilities including its Regex search abilities.

The Regex search ability is probably my favorite so far. It has helped me figure out some of the more difficult problems and is extremely fast. I am live filtering on about 12,000 documents or so and checking for values that could be anywhere within a single property of the document and I am getting results back within a second. Regex has also allowed me to get around a missing feature of Mongo that is sorely missed and is probably my only issue with the database; there is no $and operator for the queries. You can do $or, $all, $in, $exists, $ne (not equals), and a bunch of other operators, but no $and. Here is a quick scenario to show why this is missed:

Here are three fake documents. Each one has an id and a tag. The tag just contains a few letters and the user is allowed to enter letters to try and find out if they are in the tag string. The user is expecting only the documents that have ALL of the letters in the tag string to come back, and the letter do not have to be in any particular order.

1
2
3
4
5
6
7
8
9
10
11
12
  {
    _id:'Doc1',
    tag:'ABCDE'
  }
  {
    _id:'Doc2',
    tag:'CBDAE'
  }
  {
    _id:'Doc3',
    tag:'BDAE'
  }

So the user enters in the values of B and C. Doc1 and Doc2 should be returned by not Doc3 because it is missing the letter C. Here is how I would want to create this query:

1
2
3
  $query1 = new MongoRegex('/B/i');
  $query2 = new MongoRegex('/C/i');
  $collection->find('$and'=>array('tag'=>$query1, 'tag'=>$query2));

I am using MongoRegex to create a Regex object that Mongo will understand. Both Regex objects are looking for a single character, and with the $and operator in the query, both regex queries have to return true to return the document. Now this is a very simple example but you can see why it would be useful to have to. Instead I had to resort to pure Regex. Here is the solution I ended up putting in place to handle this exact problem:

1
2
3
4
5
6
  $lettersAry = array();
  foreach($letters as $letter){
    $lettersAry[] = "(?=.*$letter)";
  }
  $regex - '/^'.implode('',$lettersAry).'.*$/i';
  $collection->find('tag'=>new MongoRegex($regex));

That works perfectly for what I need and it puts all of the value checks into one regex object and makes it very easy to pass in as many letters as I want. Is this the perfect solution? Probably not. Does it do the trick? Most definitely.

Summary

Ok, so I didn't have too much to say I guess. I am still working on my app and I don't want to talk about it too much until it is closer to being finished. Hopefully I will be wrapping things up in the new few weeks and I will be able to share more. I will say that MongoDB is very fast, and is very easy to use. I have been able to just focus on my app and less on the database because of this. I haven't had to map out my entire database before I even touched a line of code, instead my database has morphed as I have worked on it. Need to add a new field? Oh well, throw it into the code and it is added! Yay! As a developer working on a side project I really don't want to have to think about the database more than I have too. I just want a place to dump my data and make it easy and fast to retrieve it. Thank you MongoDB for be my data dumping ground.

**Update** Ok, so I have re-written my code to use Kristina's suggestion and I got it working. Not sure why that didn't work for me the first few times I tried but I must have had something all screwy.

Comments (3) Trackbacks (0)
  1. You can use $all for your query:

    $collection->find(array(‘tag’ => array(‘$all’ => array($query1, $query2))));

    That will return Doc1 and Doc2.

    I’m glad the PHP driver is working out for you, let me know if you have any suggestions on the documentation!

    • You are correct. For some reason each time I tried that I never got a result set back. Even messing with it after reading your comment a few times I still did not get anything back, but then I finally just got it working. Not sure what I was doing wrong when it wasn’t working but I should be able rebuild my query a bit to fit that in, though now I am not sure if I really need it now that I got the regex giving me the same results. I will put an update in the post tonight to correct it.

      Thanks for your comment! And thank you so much for all the work you put into the driver, it works wonderfully.

      Also, great blog you have. I just found a new RSS feed to start reading and Twitter profile to follow, you have some really great stuff there.

      Thanks again. :)


Leave a Reply

No trackbacks yet.