2016-01-29 2 views
2

У меня есть приложение meteorjs с коллекцией с полем ticker.
мне нужно $where заявление, потому что я хочу, чтобы сравнить два поля в одной и той же коллекции:

Tickers.find({$where: function() { return (this.price < this.value); }}) 

Он не работал, и я сделал простой тест с $where.
На стороне сервера, когда я запускаю этот запрос:

var t = Tickers.find({ticker:'AAPL'}); 

t содержит правильное значение: один элемент со значением тикер «AAPL». Когда я пользуюсь:

t = Tickers.find({$where: function() { return (this.ticker === 'AAPL'); }}); 

t содержит все предметы в коллекции.
Тот же вопрос $where работает на стороне клиента, но я не хочу публиковать (огромную) коллекцию для выполнения запроса на стороне клиента.

+0

Можете ли вы уточнить, как это не сработало? Получаете ли вы ошибку или неправильное значение? – terrafirma9

ответ

3

Вам необходимо передать $where Функция как строка, а не как фактическая функция. Это необходимо для Mongo для обработки и запуска функции (она не выполняется в Node.js). Следуйте этому forum thread для получения дополнительной информации об этом.

Таким образом изменить ваш запрос

Tickers.find({"$where": "function() { return (this.price < this.value); }"}) 

или просто передать в сравнении строк

Tickers.find("this.price < this.value"); 

Однако, имейте в виду, что это не будет perfom очень хорошо, так как с помощью оператора в $where вызывает JavaScript-движок для оценки кода Javascript на каждом документе и проверки условий для каждого. Целесообразно комбинировать с индексированными запросами, если вы можете так, чтобы запрос мог быть быстрее.

Некоторые considerations вы должны смотреть на при использовании $where:

Не использовать глобальные переменные.

$where оценивает JavaScript и не может использовать индексы. Поэтому производительность запросов улучшается, когда вы выражаете ваш запрос используя стандартные операторы MongoDB (например, $gt, $in). В общем, вы должны использовать $where только если вы не можете выразить свой запрос, используя другой оператор . Если вы должны использовать $where, попробуйте включить стандартный оператор запроса для фильтрации набора результатов. Использование $where требует сканирования таблицы.Используя нормальные Непро- $where операторов запросов обеспечивают следующие эксплуатационные преимущества:

MongoDB будет оценивать Непро- $where компонентов запроса перед тем $where заявления. Если заявления не соответствуют никаким документам, MongoDB не будет выполнять оценку какого-либо вопроса, используя $where . Операторы запроса могут использовать индекс.

Еще одно предложение, что позволяет избежать использования оператора в $where бы создать дополнительный вычисляемый денормализованным поле сказать price_difference, что разница между ценой и стоимостью (стоимость - цена), которые затем можно запросить как:

Tickers.find({ "price_difference": { "$gt": 0 }}); 

Но все же такие поля с низкой степенью селективности не дают хорошей производительности индекса, если коллекция очень велика, поэтому кандидат, установленный для индексирования, является большим с этим подходом.

+1

Спасибо cridam за хорошую идею: я создам дополнительное вычисленное денормализованное поле. –