Wednesday 12 February 2014

Finding What You're Looking For

Finding What You're Looking For

A previous blog entry looked at simple searching with find(). Now we will look deeper into building queries. This blog covers:
  • Numbers and searching ranges
  • Arrays and searching in them
  • Building logical expressions
  • Regular expressions for super flexible searching

Numbers and Ranges

Numeric data is inserted into MongoDB without quotes, just as we'd treat a number in any programming language:

db.eg.insert({Name : "Bill", Age : 18})
db.eg.insert({Name : "Ted", Age : 17})

and we can search for exact numbers:

db.eg.find({Age:17})

or those in a range:

db.eg.find({Age: {$lt : 18}})

Other useful operators include:

  • $lte - Less than or equal
  • $gt - Greater than
  • $gte - Greater than or equal
  • $ne - Not equal

Inserting and Searching Arrays

To search for each and any of an array of possible matches on the same field, you can specify an array of target values. This is better than a string of $or operators.

db.eg.find({Name : { $in : ["Bill" , "Ted"]}})

Note the [ ] square brackets to  denote the array.

You can insert an array as a value in a document:

db.eg.insert({Likes: ["Ice cream","Apples","Chocolate"]})

and search for one or more items in it:

db.eg.find({Likes: { $in: ["Apples","Gin"]}})

If you want to match a single term to the array, the single term still needs to be in an array of length one:

db.eg.find({Likes: { $in: ["Apples"]}})

The opposite of $in is $nin, which means not in.

Building Logical Expressions

I've already hinted at it: you can build logical expressions for a search using $and, $or, $not and $nor. A simple AND is implemented implicitly by MongoDB if you provide a comma separated list of matches:

db.eg.find({Name: "Bill", Age: 18})

is the same as

db.eg.find({$and: [{Name: "Bill"}, {Age: 18}]})

but we must be explicit if we want to use OR:

db.eg.find({$or: [{Name: "Bill"}, {Age: 17}]})

$Not does as you'd expect and $nor means not and not.

Finally, if you want to specify more complex matches on a single value, you can use regular expressions, which are described below:

Searching with Regular Expressions

You can build some reasonably complex searches with a mixture of AND, OR, and NOT, but logical expressions are less useful if you want to match certain classes of string. For example, a search to find all the names that include a number (Like Joe90 or Ben10). For this, we need regular expressions.

There are two ways to tell MongoDB you want to use a regular expression. One is to use the Javascript notation and the other is to use the MongoDB $regex operator.

The Javascript notation puts the regular expression between slashes, followed by any options. Here is the syntax:

/expression/options

and the $regex operator makes things explicit:

{ $regex: 'expression', $options: 'options' }

And now some examples from a collection called db.colc:


find({Name: /ev/}) Find names that contain "ev" anywhere
find({Name: /^K/i}) Find names that start with "K", ignoring case (K or k)
find({Name: /[abc]/}) Find names that contain "a" or "b" or "c" anywhere
find({Name: /\w{1,}\d{1,}/}) Find names that end with some numbers

It all looks a bit cryptic, but you get the idea - you can specify pretty much any pattern you want. To do it confidently off the top of your head takes a bit of practice, but its worthwhile as regular expressions have many other uses. Once you can do it in Javascript, for example, you can validate web forms before they are submitted.

A bit more information on regular expressions in MongoDB can be found here. For more details on the Javascript method of defining regular expressions, look here.




No comments:

Post a Comment