我使用mongo查询来计算每个项目的总价。我的查询看起来像
$queryBuilder=新查询\生成器($this,$documentName);
$queryBuilder->field('created')->gte($startDate);
$queryBuilder->field('is_test_value')->notEqual(true);
..........
$queryBuilder->map('function() {emit(this.item, this.price)}');
$queryBuilder->reduce('function(item, valuesPrices) {
return {sum: Array.sum(valuesPrices)}
}');
这是有效的,没问题。但我发现,在某些情况下(200个结果中大约有20个),我在字段sum
中有奇怪的结果,而不是总值,我看到的是类似的结构
[objectObject]444444444444444
4-是项目的价格。
我试着把reduce块替换成这样的块:
var sum = 0;
for (var i = 0; i < valuesPrices.length; i++) {
sum += parseFloat(valuesPrices[i]);
}
return {sum: sum}
在这种情况下,我看到NAN
值。
我怀疑字段price
中的某些数据插入错误(不是以浮点形式,而是以字符串、对象等形式)。我尝试从mongocli执行查询,发现所有价格值都是整数。
这一点都不"奇怪"。你"违反了规则",现在你正在为此付费。
- MongoDB可以对同一个键多次调用reduce函数。在这种情况下,reduce功能对该键的上一次输出将成为该键下一次reduce调用的输入值之一
mapReduce
的主要规则(如前所述)是必须从"reducer"返回与从"mapper"返回完全相同的结构。这是因为"reducer"实际上可以为同一个"key"运行多次。这就是mapReduce
处理大型列表的方式。
你可以通过返回一个奇异值来解决这个问题,就像你在emit:中所做的那样
return Array.sum(values);
然后就不会有问题了。向中添加一个对象键会使数据不一致,因此当"reduced"结果再次反馈到"reducer"时会出现错误。