Reputation: 1215
I have a meteorjs application with a collection with a ticker
field.
I need the $where
statement because I want to compare two fields in the same collection:
Tickers.find({$where: function() { return (this.price < this.value); }})
It didn't worked and I did a simpler test with $where
.
On server side, when I run this query:
var t = Tickers.find({ticker:'AAPL'});
t
contains the right value: one item with 'AAPL' ticker value. When I use:
t = Tickers.find({$where: function() { return (this.ticker === 'AAPL'); }});
t
contains all the items in the collection.
The same $where
query instead on client side works, but I don't want to publish the (huge) collection to do the query on client side.
Upvotes: 2
Views: 388
Reputation: 103305
You need to pass the $where
function as a string, not as an actual function. This is needed for Mongo to process and run the function (it is not being done in Node.js). Follow this forum thread for more on this.
Thus change your query to
Tickers.find({"$where": "function() { return (this.price < this.value); }"})
or simply pass in the string comparison
Tickers.find("this.price < this.value");
However, bear in mind that this won't perfom very well since using the $where
operator calls the JavaScript engine to evaluate Javascript code on every document and checks the condition for each. It is advisable to combine with indexed queries if you can so that the query may be faster.
Some considerations you have to look at when using $where
:
Do not use global variables.
$where
evaluates JavaScript and cannot take advantage of indexes. Therefore, query performance improves when you express your query using the standard MongoDB operators (e.g.,$gt
,$in
). In general, you should use$where
only when you can’t express your query using another operator. If you must use$where
, try to include at least one other standard query operator to filter the result set. Using$where
alone requires a table scan. Using normal non-$where
query statements provides the following performance advantages:MongoDB will evaluate non-
$where
components of query before$where
statements. If the non-$where
statements match no documents, MongoDB will not perform any query evaluation using$where
. The non-$where
query statements may use an index.
Another suggestion that avoids using the $where
operator would be to create an additional computed denormalized field say price_difference
that is the difference between price and value (value - price) which you can then query as:
Tickers.find({ "price_difference": { "$gt": 0 }});
But still, such low-selectivity fields don't yield good index performance if the collection is very large thus the candidate set for indexing is large with this approach.
Upvotes: 3