views:

40

answers:

3

I have been using MongoDB and the Ruby driver and Mongoid, and lines

db.things.find({j: {$ne: 3}, k: {$gt: 10} });

just seem so weird and hard to remember. Why not use a parser:

db.things.find("j != 3 && k > 10")

which can automatically convert to its desired form? (or whatever form it uses internally).

+1  A: 

MongoDB supports JavaScript expressions in find() statements. Just be aware that:

Javascript executes more slowly than the native operators [...] but is very flexible.

The JavaScript expression string is parsed into actual JavaScript once, which is then evaluated for each document.

However, the JavaScript is not converted to native operators, such as { $ne: 3 }. The reason for this is that not all JavaScript can be expressed using native operators.

Because it cannot convert the expression into native operators, it (probably) also doesn't know which indexes to use. As a result, JavaScript expressions can be somewhat slower than native operators.

Niels van der Rest
i'd imagine it could parse it once and use it in the querying. parsing once should be really fast that is not even noticeable?
動靜能量
The parsing is not the problem. The JS is evaluated for every document, no indexes will be used. It is not a translation into an equivalent internal query with $ne/$gt...
Thilo
@Jian Lin: Parsing is done once, but no conversion takes place. See my updated answer.
Niels van der Rest
@Niels so can it translate it *when* it can be represented by native operators and use the translated version? many conditions can be merely gt, gte, eq, and ne, with some simple `and`, `or`.
動靜能量
@Jian Lin: In theory it could, but I don't know if it does. I'm not familiar with the [source code](http://github.com/mongodb/mongo), so I couldn't find the answer. You can try asking here on SO, or directly in the [MongoDB user group](http://groups.google.com/group/mongodb-user?pli=1).
Niels van der Rest
+2  A: 

As an alternative, it would not be too difficult to implement a query builder with a fluent interface. Not sure if the Ruby driver already includes one, but the Java version has

DBObject condObj =
   QueryBuilder.start("numberOfPageHits").greaterThan(10)
      .and("name").regex(regExp).get();
Thilo
thanks, I was looking for that.
Kaustubh P
+1  A: 

Take a look at http://github.com/RedBeard0531/MongoMagic. Its written in python but should be easy to translate to ruby. Your query would look something like this:

db.things.find(AND( M.j != 3 , M.k > 10 ))
mstearn