我有.json文件,我已导入我的收藏夹。
{
"_id" : ObjectId("5739ee85daa49f685e316fc6"),
"id" : 38,
"title" : "It Takes Two (1995)",
"genre" : "Comedy",
"ratings" : [
{
"userId" : 26,
"rating" : 2
},
{
"userId" : 531,
"rating" : 2
},
{
"userId" : 1054,
"rating" : 2
},
{
"userId" : 1068,
"rating" : 2
},
{
"userId" : 1221,
"rating" : 5
},
{
"userId" : 1434,
"rating" : 4
},
{
"userId" : 1448,
"rating" : 1
},
{
"userId" : 1645,
"rating" : 5
},
{
"userId" : 1647,
"rating" : 1
},
{
"userId" : 1958,
"rating" : 3
},
{
"userId" : 2010,
"rating" : 1
},
{
"userId" : 2042,
"rating" : 1
},
{
"userId" : 2063,
"rating" : 1
},
{
"userId" : 2106,
"rating" : 1
},
{
"userId" : 2116,
"rating" : 3
},
{
"userId" : 2541,
"rating" : 5
},
{
"userId" : 2777,
"rating" : 3
},
{
"userId" : 3013,
"rating" : 2
},
{
"userId" : 3029,
"rating" : 2
},
{
"userId" : 3111,
"rating" : 4
},
{
"userId" : 4387,
"rating" : 1
},
{
"userId" : 4572,
"rating" : 5
},
{
"userId" : 5361,
"rating" : 5
}
]
}
我想做一些地图缩减,以便向所有用户显示他们的评论总数及其平均值。
我试过了:
var map = function(){emit(this.ratings.userId, 1);}
var reduce = function(key, values){var res = 0;
values.forEach(function(v){ res += 1});
return {count: res};
}
db.movie.mapReduce(map, reduce, { out: "users" });
db.users.find()
{ "_id" : null, "value" : { "count" : 39 } }
我不知道,为什么它显示 _id" :null 。我想 this.ratings.userId 错了。但是this.ratings [userId]也不起作用。
我期待的是:
userId:10, count:2000
userId:20, count:500
你能帮忙吗?
答案 0 :(得分:3)
您使用的是错误的工具。您需要使用aggregate()
方法来访问聚合管道。在您的管道中,您需要对"评级"进行去标准化。使用$unwind
运算符的数组。从那里你可以通过" userId"并使用$sum
和$avg
累加器运算符分别返回字段的总和和平均值。
db.movie.aggregate([
{ "$unwind": "$ratings" },
{ "$group": {
"_id": "$ratings.userId",
"count": { "$sum": 1 },
"average": { "$avg": "$ratings.rating" }
}}
])
答案 1 :(得分:0)
我找到了解决方案:
var mapFunction = function() {
for (var idx = 0; idx < this.ratings.length; idx++) {
var key = this.ratings[idx].userId;
var value = {
count: 1,
rating: this.ratings[idx].rating
};
emit(key, value);
}
};
var reduceFunction = function(keyUSERID, countObjVals) {
reducedVal = { count: 0, rating: 0 };
for (var idx = 0; idx < countObjVals.length; idx++) {
reducedVal.count += countObjVals[idx].count;
reducedVal.rating += countObjVals[idx].rating;
}
return reducedVal;
};
var finalizeFunction = function (key, reducedVal) {
reducedVal.avg = reducedVal.rating/reducedVal.count;
return reducedVal;
};
db.movies.mapReduce( mapFunction,
reduceFunction,
{
out: "users",
finalize: finalizeFunction
}
)
db.users.find()给了我:
{ "_id" : 1, "value" : { "count" : 56, "rating" : 237, "avg" : 4.232142857142857 } }
{ "_id" : 2, "value" : { "count" : 129, "rating" : 479, "avg" : 3.7131782945736433 } }
{ "_id" : 3, "value" : { "count" : 51, "rating" : 199, "avg" : 3.9019607843137254 } }
{ "_id" : 4, "value" : { "count" : 21, "rating" : 88, "avg" : 4.190476190476191 } }
{ "_id" : 5, "value" : { "count" : 198, "rating" : 623, "avg" : 3.1464646464646466 } }