Nodejs 看个Mongodb -〉mapReduce sort的问题。
Nodejs 看个Mongodb -〉mapReduce sort的问题。
异常是这个: exception: could not create cursor over nodejs.loginHistory for query : {} sort : { times: 1 } 上代码:
// map-reduce
var map = function(){
emit(this.user.username , {userinfo : this.user, count : 1});
};
var reduce = function(key, vals){
var result = {userinfo : null, count : 0};
if(vals && vals.length > 0){
result.count = vals.length;
result.userinfo = vals[vals.length-1].userinfo;
}
return result;
};
var opts = {limit : 10 ,out : {inline:1} }; //sort : {'times': -1} ,
db.collection('loginHistory').mapReduce(map,reduce, opts, function (err,datas){
// console.log(err);
// console.log(util.inspect(datas));
res.json( {err: err, datas:datas } );
});
\n```
在var opts = {limit : 10 ,out : {inline:1} }; 这里我这个sort是这样的sort : {'times': -1} , 但加上后就报那个错。
有知道的朋友帮忙回复下。
Node.js 中 MongoDB 的 mapReduce 和排序问题
背景信息
你遇到了在使用 MongoDB 的 mapReduce
方法时,尝试添加排序(sort
)功能导致的错误。具体来说,你在 opts
对象中添加了 sort
属性,结果引发了错误。
错误原因
在 MongoDB 的 mapReduce
方法中,sort
属性并不被直接支持。mapReduce
是一个复杂的操作,它包括映射(map)、归约(reduce)以及输出(output),但它并没有内置对查询结果排序的支持。
解决方案
要在 mapReduce
结果中实现排序,可以考虑以下两种方法:
- 在客户端排序:在
mapReduce
操作完成后,在客户端进行排序。 - 使用聚合管道(Aggregation Pipeline):聚合管道提供了更灵活的操作,包括排序、过滤等功能。
这里提供第二种方法的示例代码:
// 使用聚合管道代替 mapReduce
db.collection('loginHistory').aggregate([
{
$group: {
_id: "$user.username",
userinfo: { $last: "$user" },
count: { $sum: 1 }
}
},
{
$sort: { "count": -1 } // 按 count 倒序排序
},
{
$limit: 10 // 只取前 10 条记录
}
], function (err, result) {
if (err) {
console.error("Error executing aggregate pipeline:", err);
res.json({ err: err });
} else {
res.json({ datas: result });
}
});
示例代码解释
- $group: 将文档按用户名分组,并计算每个用户的登录次数 (
count
)。同时保留每个用户最后一条登录记录的用户信息 (userinfo
)。 - $sort: 按照
count
字段倒序排序结果。 - $limit: 限制返回的结果数量为前 10 条。
这种方法不仅避免了 mapReduce
的复杂性,还利用了 MongoDB 聚合管道的强大功能来实现排序和限制结果数量的功能。
sort 里的索引必须是在集合上已定义过的索引,如果尚未定义 sort key 匹配的索引将会报错。
在MongoDB的mapReduce
中,直接添加sort
选项会导致错误。mapReduce
并不支持直接在opts
对象中指定排序参数。你需要先运行find
查询来获取排序后的数据,然后再应用mapReduce
。
以下是如何修改你的代码以实现排序:
db.collection('loginHistory')
.find({}) // 你可以根据需要调整查询条件
.sort({ times: -1 }) // 按 'times' 字段降序排序
.limit(10) // 限制结果数量
.mapReduce(
function() {
emit(this.user.username, { userinfo: this.user, count: 1 });
},
function(key, vals) {
var result = { userinfo: null, count: 0 };
if (vals && vals.length > 0) {
result.count = vals.length;
result.userinfo = vals[vals.length - 1].userinfo;
}
return result;
},
{ out: { inline: 1 } }, // 或者可以设置为一个集合名 { out: "outputCollection" }
function(err, res) {
if (err) {
console.error("Error:", err);
} else {
res.json({ err: err, datas: res });
}
}
);
这段代码首先对查询结果进行排序和限制,然后将排序后的数据传递给mapReduce
函数。这样可以避免因直接在opts
中添加sort
选项而导致的错误。