我有一个带有ticker
字段的集合的meteorjs应用程序。
我需要$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 :(得分:3)
您需要将 $where
函数作为字符串传递,而不是作为实际函数传递。这是Mongo处理和运行函数所需要的(它不是在Node.js中完成的)。有关详细信息,请按此forum thread进行操作。
因此将您的查询更改为
Tickers.find({"$where": "function() { return (this.price < this.value); }"})
或简单地传递字符串比较
Tickers.find("this.price < this.value");
但是,请记住,由于使用 $where
运算符调用JavaScript引擎来评估每个文档上的Javascript代码并检查每个文档的条件,因此这不会很好。如果可以的话,建议与索引查询结合使用,以便查询可以更快。
使用 considerations 时,您需要注意一些 $where
:
不要使用全局变量。
$where
评估JavaScript并且无法利用索引。 因此,在表达查询时,查询性能会提高 使用标准的MongoDB运算符(例如,$gt
,$in
)。一般来说,你 只有当您无法使用其他人表达您的查询时,才应使用$where
运营商。如果您必须使用$where
,请尝试至少包含一个 标准查询运算符,用于过滤结果集。仅使用$where
需要表扫描。使用普通的非$where
查询语句 提供以下性能优势:MongoDB将在
$where
之前评估查询的非$where
组件 声明。如果非$where
语句不匹配任何文档,则MongoDB 不会使用$where
执行任何查询评估。非$where
查询语句可以使用索引。
避免使用 $where
运算符的另一个建议是创建一个额外的计算非规范化字段,说price_difference
,即价格和价值之间的差异(价值 - 价格)然后您可以查询:
Tickers.find({ "price_difference": { "$gt": 0 }});
但是,如果集合非常大,这样的低选择性字段不会产生良好的索引性能,因此使用这种方法索引的候选集很大。