Shift8 Creative Graphic Design and Website Development

MongoDB Queries with Lithium: Part Two

Posted by Tom on Fri, Aug 13 2010 10:46:00

Let's take a step back for part two. Let's ignore complex (or any) objects and here we're going to go over some more basic (and common) queries that you may need to make. No, there's not really much order to the queries I'm going to go over in this series, sorry. It started as more of an "I'll post about what I'm doing as I do it." type of thing, but I'll try to go over some of the basics now. In fact, if you keep the MongoDB documentation site open for reference as you're coding, I guarantee that most queries you'll need won't be that hard.

Those of you coming from a strong love of MySQL will appreciate part two here. I'm going to go over what will replace your IN() and NOT IN() and I'll even brush on LIKE at the end of this post.

Equal To and In ($in)
So, probably your most basic query will be finding something by a specific value. We typically look up by id and we can do this in Lithium and it's been documented elsewhere. So if you've used Lithium and you've done this type of query, this will bore you...But it's good to point out that the following two conditions are basically the same.

$conditions = array('title' => 'BBQ Chicken');
$conditions = array('title' => array('BBQ Chicken'));

You can simply use a string value for the "title" key (the key being the field name in your collection in MongoDB). These aren't literally the same thing of course, the array() means to go get multiple. So you can add to that list and you've got yourself an $in basically. Here, these two are also work the same:

$conditions = array('title' => array('BBQ Chicken', 'More Chicken'));
$conditions = array('title' => array('$in' => array('BBQ Chicken', 'More Chicken')));

I suppose a difference here is that the first set of conditions would work if you were using MySQL or MongoDB with Lithium. The minute you start using specific operators for MongoDB (all those with dollar signs) then you're no longer coding in a database agnostic fashion. Which probably isn't a real big deal, unless you were trying to make some sort of application that could run with whatever database desired.

Not Equal To ($ne) and Not In ($nin)
Of course we have the opposite available to us as well. These will not be database agnostic, but you can run:

$conditions = array('title' => array('$ne' => 'BBQ Chicken'));
$conditions = array('title' => array('$nin' => array('BBQ Chicken', 'More Chicken')));

$ne being "not equal to" and $nin being "not in". The equivalent of <> and NOT IN() for MySQL users. You can probably start to see how all the operators are translated into this array format in Lithium's Model::find() method. Once you see a few you can pretty much assume the rest will be similar.

LIKE, as in Like Regular Expressions
So real quick I'm going to touch base on the equivalent of a MySQL LIKE in MongoDB. MongoDB is actually way cool in that it lets you run regular expressions! You can't simply put title => '/regex/'... That won't work because you're not technically defining a regular expression, you're defining a string. PHP has no RegExp() object class like JavaScript does. However, that PECL extension you installed for MongoDB does have a class to help you out here. So in order to use Lithium's find with a regex, you'll write something like this:

$conditions = array('title' => new \MongoRegex('/chicken/i'));

This is of course a very basic regular expression, but you do have the ability to create quite complex expressions and also take advantage of some flags; you can look here for the currently supported flags. Above you can see that I'm using the case insensitive flag. Those conditions would return me all of my chicken recipes.

Lithium also accounts for MongoRegex() as well so you don't actually need to create a new MongoRegex() object yourself. You could also write:

$conditions = array('title' => array('like' => '/chicken/i'));

For those of you not familiar with Lithium, let me glue it together for you. The Model::find() method is extremely powerful and simple to use in Lithium and it will help you make queries very quickly. You will write less code, things will look organized, and you won't be pulling your hair out. Not that I think using the straight up MongoDB extension is all too complex, but Lithium makes things a little nicer for you.

$recipes = Recipe::find('all', array('conditions' => array('title' => array('like' => '/chicken/i'))));

In a simple example, but keep in mind that aside from "conditions" you also have keys like "limit" and "fields" available to you in order to return a more specific set of data. $recipes here will be an object with all of my recipes with chicken in their titles. $recipes->data() would then return an array from that object for me to use nicely in my view template. That's one powerful short line of code. Typically to run the query you would be talking about establishing the connection first. You'd write more lines of code. Lithium makes things pretty easy, right?! Due to the speed of MongoDB this also might serve as your site's search engine. Not too shabby. Stay tuned for more, I'll get back to some of the more complex (and sometimes strange and probably not often used...but fun) queries you can make with Lithium and MongoDB.


[Back To Blog Index]