首页 文章

在MongoDB中按查询聚合分组,按日期显示前5个$ count结果[重复]

提问于
浏览
2

这个问题在这里已有答案:

我是应用程序堆栈上MongoDb的新手,从LAMP(mysql后端)切换到MEAP(mongo后端),所以请原谅我对非关系查询的无知 .

我正在尝试对MongoDb中的数据进行一些简单的分析,以便为特定关键字的用户呈现一段时间内的趋势 .

我的(简化)集合对象结构如下所示:(在BSON中)

{
  "_id" : ObjectId("55aae6b21e76a5d02945ccbc"),
  "article" : {
    "category" : [{
        "title" : "Foods"
      }
    ]},
  "published" : new Date("7/17/2015 19:00:00")
}

想象一下,每天都有很多文章发表,每篇文章都有很多可能的“类别”,所以为了简洁,上面的对象被截断了 .

我想向用户呈现每天发布的“前5名”计数,这样他们就可以了解趋势,等等......

这是我在mongo中的聚合查询的尝试,它目前只是总结所有类别,无论发布日期如何:

{ "$unwind": "$article.category" },
{"$group":
    {
        "_id":  "$article.category.title" ,
        "count": { "$sum" : 1 }
    }
},
{ "$sort" : { "count" : -1, "_id": 1} },
{ $limit : 5 }

产生如下结果:

{ 0: {"_id": "Foods", "count": 50},
  1: {"_id": "Recipes", "count": 45},
   ...
}

问题:如何根据我的收藏中提供的“已发布”日期对结果进行分组?伪对象的结构类似于:

Date: 7/17/2015
    category: Foods, count: 25
    category: Recipes, count: 20
    ... continue top 5 results for that date
Date: 7/18/2015
    category: Foods, count: 25
    category: Recipes, count: 25
    ... continue top 5 results for that date
etc...

任何帮助这个mongo newb非常感谢 . 我一直在考虑将两个group by语句组合在一起,并试图找出$ push或$ addtoset可以帮助我,但我无法绕过文档以使其适用于我的示例

2 回答

  • 0

    您可能正在寻找的是Mongo Date Aggregation Operators . 您需要做的是按类别 Headers 对文档进行分组,使用 $year$dayOfYear (或 $month$dayOfMonth )运算符对日期进行分组,这样您的数组中的每个元素都将按日期和 Headers 唯一 .

    与运算符一起,您需要在结果上运行 map 以将类别限制在前5位,因为我不知道在聚合调用中直接执行此操作的方法 .

    我的策略是:

    • 展开类别 .

    • 组合在一起并按类别和日期(日期和年份)进行计数 .

    • 按类别(及其计数)按日期分组推送到数组 .

    • 在结果上使用 map 以截断前5个以外的类别 .

    这可能是您正在寻找的查询:

    db.articles.aggregate([{
      "$unwind": "$article.category"
    }, {
      "$group": {
        "_id":  {
          title: "$article.category.title",
          year: { $year: "$published" },
          day: { $dayOfYear: "$published" }
        },
        "count": { "$sum" : 1 }
      }
    }, {
      $group: {
        _id: {
          year: "$_id.year",
          day: "$_id.day"
        },
        categories: {
          $push: { title: "$_id.title", count: "$count" }
        }
      }
    }]).map( function (data) {
      // Using map here is the best way I could think to limit
      // the array size. Perhaps someone can do it all together
      // But this should do the trick.
      data.categories.sort( function (a, b) {
        return b.count - a.count;
      });
      data.categories = data.categories.slice(0, 5);
      return data;
    });
    

    我希望结果看起来像这样:

    [{
      _id: {
        year: 2015,
        day: 123
      },
      categories: [{
        title: "Food",
        count: 3
      }, {
        title: "Recipes",
        count: 2
      }]
    }, ...]
    
  • 0

    虽然目前目前不可能使用聚合框架拼接数组(此功能很快将在mongoDB version 3.1.4中提供)但您仍然可以通过followng管道非常接近您想要的内容:

    [
    {
        "$project": {
            "article": "$article",
            "yymmdd": {
                "$dateToString": {
                    "date": "$published",
                    "format": "%Y-%m-%d"
                }
            }
        }
    },
    {
        "$unwind": "$article.category"
    },
    {
        "$group": {
            "count": {
                "$sum": 1
            },
            "_id": {
                "yymmdd": "$yymmdd",
                "title": "$article.category.title"
            }
        }
    },
    {
        "$sort": {
            "_id.yymmdd": 1,
            "count": -1
        }
    },
    {
        "$group": {
            "item": {
                "$push": {
                    "count": "$count",
                    "item": "$_id.title"
                }
            },
            "_id": "$_id.yymmdd"
        }
    }
    

    ]

    哪些数据会以下列形式给出结果集:

    {u'item': [{u'count': 100, u'item': u'food'}, {u'count': 99, u'item': u'cinema'}, {u'count': 96, u'item': u'tennis'}, {u'count': 92, u'item': u'news'}, {u'count': 91, u'item': u'gossip'}, {u'count': 90, u'item': u'football'}, {u'count': 88, u'item': u'recipes'}, {u'count': 84, u'item': u'tv'}], u'_id': u'2015-05-31'}
    {u'item': [{u'count': 96, u'item': u'gossip'}, {u'count': 93, u'item': u'news'}, {u'count': 92, u'item': u'food'}, {u'count': 91, u'item': u'football'}, {u'count': 87, u'item': u'tennis'}, {u'count': 84, u'item': u'recipes'}, {u'count': 84, u'item': u'cinema'}, {u'count': 82, u'item': u'tv'}], u'_id': u'2015-05-29'}
    {u'item': [{u'count': 106, u'item': u'cinema'}, {u'count': 104, u'item': u'gossip'}, {u'count': 99, u'item': u'tv'}, {u'count': 98, u'item': u'news'}, {u'count': 96, u'item': u'football'}, {u'count': 94, u'item': u'food'}, {u'count': 93, u'item': u'tennis'}, {u'count': 90, u'item': u'recipes'}], u'_id': u'2015-05-25'}
    {u'item': [{u'count': 85, u'item': u'football'}, {u'count': 85, u'item': u'gossip'}, {u'count': 81, u'item': u'cinema'}, {u'count': 80, u'item': u'tennis'}, {u'count': 78, u'item': u'news'}, {u'count': 74, u'item': u'recipes'}, {u'count': 70, u'item': u'food'}, {u'count': 67, u'item': u'tv'}], u'_id': u'2015-05-22'}
    

    每个项目数组按 Headers 出现次数排序 . 然后在应用程序中,您可以将此数组拼接为n以获得前N个计数 . 你可以看看重现它的步骤in this example (in python)

相关问题