急!!!在线等关于mongoose的mapReduce的Nodejs问题

急!!!在线等关于mongoose的mapReduce的Nodejs问题

var o = {};
o.map = function() { emit(this.shopId, this.score); };
o.reduce = function(k, vals) { return { sum: Array.sum(vals), count: vals.length }; };
self.model.mapReduce(o, function(err, items) {
console.log(items);
});

怎么出来的结果跟我预想的不对?

 [ { _id: 52b6e1ac3bcdfc6e7fe491d4, value: 3 } ]

预想的不应该是这样的吗:

 [ { _id: 52b6e1ac3bcdfc6e7fe491d4, value: { sum: BLAHBLAH, count: BLAHBLAH } } ]

9 回复

当然可以。让我们一起来分析一下你的代码,并解释为什么你得到的结果与预期不符。

代码分析

首先,让我们看看你提供的代码:

var o = {};
o.map = function() { emit(this.shopId, this.score); };
o.reduce = function(k, vals) { return { sum: Array.sum(vals), count: vals.length }; };

self.model.mapReduce(o, function(err, items) { 
    console.log(items);
});

问题分析

你希望使用 mapReduce 来计算每个 shopId 的评分总和以及评分数量。然而,你发现输出的结果并不是你期望的形式。

问题原因

问题出在 reduce 函数中。Mongoose 的 mapReduce 方法默认返回的是原始值,而不是你在 reduce 函数中定义的对象。你需要明确告诉 Mongoose 你希望它返回一个对象。

解决方案

你可以通过设置 outfinalize 参数来改变输出格式。具体来说,你可以将 out 设置为 { inline: 1 } 来直接在结果中包含 value 字段。

以下是修改后的代码:

var o = {
    map: function() { emit(this.shopId, this.score); },
    reduce: function(k, vals) { 
        return { sum: vals.reduce((a, b) => a + b, 0), count: vals.length }; 
    },
    out: { inline: 1 },
    finalize: function(key, reducedValue) {
        return reducedValue;
    }
};

self.model.mapReduce(o, function(err, items) { 
    if (err) {
        console.error(err);
    } else {
        console.log(items);
    }
});

代码解释

  1. Map 函数:这个函数用于发射键值对,其中键是 shopId,值是 score
  2. Reduce 函数:这个函数用于聚合相同 shopId 的所有 score 值,并计算总和和计数。
  3. Out 参数:设置为 { inline: 1 } 表示直接在结果中包含 value 字段。
  4. Finalize 函数:这个函数用于进一步处理减少后的值,确保它们被正确返回。

预期输出

现在,当你运行这段代码时,你应该会看到类似以下的输出:

[ { _id: 52b6e1ac3bcdfc6e7fe491d4, value: { sum: 10, count: 2 } } ]

这样,你就可以得到你期望的结果了。希望这能解决你的问题!


emit第二个参数的值类型要和reduce的返回一样,比如你这个例子,map里应该类似: emit(this.shopId, {sum: xxx, count: xxx}); 好好研究下官方示例吧。

挖个坟不知道有人帮我讲解一下挖?。。今天我研究map就是做map的然后返回值给reduce的v,然后根据自己需求在reduce里foreach v什么的在设置一个返回值出去。 也就是map做过滤 过滤后的数据给reduce 在做返回

不错 自豪地采用 CNodeJS ionic

喂喂喂,不要挖坟喂,我自己看了羞愧死了 QwQQQQQQQQQQQQ

哈哈…顶上去…让更多人挖…哈哈

From Noder

哦!楼主,我看到了哦!继续搔搔你!

原来你也发过这样的帖子,哈哈

根据你的描述,你的 mapreduce 函数看起来是正确的,但返回的结果与预期不符。问题可能在于 Array.sum 方法没有被定义。你需要确保 Array.sum 方法被正确地定义,并且能够在你的环境中使用。

你可以尝试以下代码来实现你的需求:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

// 定义一个简单的模型
var shopScoreSchema = new Schema({
    shopId: String,
    score: Number
});

var ShopScore = mongoose.model('ShopScore', shopScoreSchema);

var o = {
    map: function() { emit(this.shopId, this.score); },
    reduce: function(k, vals) { 
        var sum = vals.reduce((acc, val) => acc + val, 0);
        return { sum: sum, count: vals.length };
    }
};

ShopScore.mapReduce(o, function(err, model) {
    if (err) {
        console.error(err);
    } else {
        model.find(function(err, items) {
            if (err) {
                console.error(err);
            } else {
                console.log(items);
            }
        });
    }
});

解释

  1. 定义模型:首先我们定义了一个 shopScoreSchema 模型,包含 shopIdscore 字段。
  2. 定义 map 函数map 函数将每个文档的 shopIdscore 发射出去。
  3. 定义 reduce 函数reduce 函数计算 vals 的总和并统计数量。
  4. 执行 mapReduce:使用 ShopScore.mapReduce 执行 mapReduce 操作,传入 mapreduce 函数。
  5. 处理结果:在回调函数中处理结果,打印出最终的结果。

如果你发现输出的结果仍然不符合预期,可能需要检查数据是否正确地存储到数据库中,或者检查是否有其他因素影响了结果。

回到顶部