Database Reference
In-Depth Information
Imagine that, for each user, you've calculated a rating reliability factor. This is
essentially an integer that, when multiplied by the user's rating, results in a more nor-
malized rating. Suppose further that you want to query a particular user's reviews and
only return a normalized rating greater than 3. Here's how that query would look:
db.reviews.find({user_id: ObjectId("4c4b1476238d3b4dd5000001"),
$where: "(this.rating * .92) > 3"})
This query meets both recommendations: it uses a standard query on a presumably-
indexed user_id field, and it employs a JavaScript expression that's absolutely beyond
the capabilities of the standard query language.
In addition to recognizing the attendant performance penalties, it's good to be
aware of the possibility of JavaScript injection attacks . An injection attack becomes pos-
sible whenever a user is allowed to enter code directly into a JavaScript query. Though
there's never any danger of users being able to write or delete in this way, they might
be able to read sensitive data. An incredibly unsafe JavaScript query in Ruby might
look something like this:
@users.find({$where => "this.#{attribute} == #{value}"})
Assuming that users could control the values of attribute and value , they might
manipulate the query to search the collection on any attribute pair. Though this
wouldn't be the worst imaginable intrusion, you'd be wise to prevent its possibility.
R EGULAR EXPRESSIONS
We saw near the beginning the chapter that you can use a regular expression within a
query. In that example, I showed a prefix expression, /^Ba/ , to find last names begin-
ning with Ba , and I pointed out that this query would use an index. In fact, much
more is possible. MongoDB is compiled with PCRE ( http://mng.bz/hxmh ) , which
supports a huge gamut of regular expressions.
With the exception of the prefix-style query just described, regular expressions
queries can't use an index. Thus I recommend using them as you would a JavaScript
expression—in combination with at least one other query term. Here's how you might
query a given user's reviews for text containing the words best or worst . Note that you
use the i regex flag 9 to indicate case insensitivity:
db.reviews.find({user_id: ObjectId("4c4b1476238d3b4dd5000001"),
text: /best|worst/i })
If the language you're using has a native regex type, you can use a native regex object
to perform the query. You can express an identical query in Ruby like so:
@reviews.find({:user_id => BSON::ObjectId("4c4b1476238d3b4dd5000001"),
:text => /best|worst/i })
9
The case-insensitive option will always prevent an index from being used to serve the query, even in the case
of a prefix match.
Search WWH ::




Custom Search