【问题标题】:Return count and average of field in subdocument返回子文档中字段的计数和平均值
【发布时间】:2016-05-23 06:00:14
【问题描述】:

我已将 .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

你能帮忙吗?

【问题讨论】:

  • 您可能不需要 mapReduce。 他们的评论数量及其平均值是什么意思?
  • 例如,用户 ID“1”被评为“玩具总动员”(4.0)、“教父”(5.0)、“美国美女”(5.0)、“海底总动员”(4.0)。所以他的评论总数是4,平均值是4.5
  • 请尝试发布db.movie.find().pretty() 的输出,以便我们看到您的数据是什么样的。顺便说一句,在您的问题上使用编辑链接。不要在评论中发帖。
  • 好的,我发布了我的数据。
  • 如果您使用 mapReduce,您的错误在于地图函数“ratings”没有“userId”属性。您的 reduce 功能也需要修复。最后,要在“计数”旁边使用 mapReduce 获得平均值,您需要做的还不止这些。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您使用了错误的工具。您需要使用aggregate() 方法来访问聚合管道。在您的管道中,您需要使用 $unwind 运算符对“评级”数组进行反规范化。从那里您可以按“userId”对文档进行简单分组,并使用 $sum$avg 累加器运算符,它们分别返回字段的总和和平均值。

db.movie.aggregate([
    { "$unwind": "$ratings" }, 
    { "$group": { 
        "_id": "$ratings.userId", 
        "count": { "$sum": 1 }, 
        "average": { "$avg": "$ratings.rating" } 
    }}
])

【讨论】:

    【解决方案2】:

    我找到了解决办法:

        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 } }
    

    【讨论】:

      猜你喜欢
      • 2020-05-27
      • 2015-07-29
      • 2021-05-07
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多