Mongodb聚合框架:每天最受欢迎的标签列表

时间:2016-03-24 14:59:26

标签: mongodb aggregation-framework

这是我的db:

db.test.insert({"title": "post01", "body" : "something01", "day" : "2010/01/12", "tags" : ["nosql", "winter"]})
db.test.insert({"title": "post02", "body" : "something02", "day" : "2010/01/12", "tags" : ["sledding", "winter"]})
db.test.insert({"title": "post03", "body" : "something03", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post04", "body" : "something04", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post05", "body" : "something05", "day" : "2010/01/12", "tags" : ["nosql", "sledding"]})
db.test.insert({"title": "post06", "body" : "something06", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post07", "body" : "something07", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post08", "body" : "something08", "day" : "2010/01/12", "tags" : ["nosql", "winter"]})
db.test.insert({"title": "post09", "body" : "something09", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post10", "body" : "something10", "day" : "2010/01/12", "tags" : ["winter"]})
db.test.insert({"title": "post11", "body" : "something11", "day" : "2010/01/12", "tags" : ["nosql", "winter"]})
db.test.insert({"title": "post12", "body" : "something12", "day" : "2010/01/13", "tags" : ["soda"]})
db.test.insert({"title": "post13", "body" : "something13", "day" : "2010/01/13", "tags" : ["php"]})
db.test.insert({"title": "post14", "body" : "something14", "day" : "2010/01/13", "tags" : ["soda"]})
db.test.insert({"title": "post15", "body" : "something15", "day" : "2010/01/13", "tags" : ["soda"]})
db.test.insert({"title": "post16", "body" : "something16", "day" : "2010/01/13", "tags" : ["soda", "php"]})
db.test.insert({"title": "post17", "body" : "something17", "day" : "2010/01/13", "tags" : ["soda"]})
db.test.insert({"title": "post18", "body" : "something18", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post19", "body" : "something19", "day" : "2010/01/14", "tags" : ["nosql", "python"]})
db.test.insert({"title": "post20", "body" : "something20", "day" : "2010/01/14", "tags" : ["nosql", "python"]})
db.test.insert({"title": "post21", "body" : "something21", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post22", "body" : "something22", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post23", "body" : "something23", "day" : "2010/01/14", "tags" : ["python", "winter"]})
db.test.insert({"title": "post24", "body" : "something24", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post25", "body" : "something25", "day" : "2010/01/14", "tags" : ["nosql", "python", "winter"]})
db.test.insert({"title": "post26", "body" : "something26", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post27", "body" : "something27", "day" : "2010/01/14", "tags" : ["nosql", "winter"]})
db.test.insert({"title": "post28", "body" : "something28", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post29", "body" : "something29", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post30", "body" : "something30", "day" : "2010/01/14", "tags" : ["python"]})
db.test.insert({"title": "post31", "body" : "something31", "day" : "2010/01/14", "tags" : ["nosql", "winter"]})
db.test.insert({"title": "post32", "body" : "something32", "day" : "2010/01/14", "tags" : ["nosql"]})
db.test.insert({"title": "post33", "body" : "something33", "day" : "2010/01/14", "tags" : ["nosql", "python"]})
db.test.insert({"title": "post34", "body" : "something34", "day" : "2010/01/14", "tags" : ["nosql"]})

我想获得最近N天最流行的标签列表,例如:

{ "day" : "2010/01/14", "tags" : { "python" : 6, "winter" : 4, "nosql" : 15 ] }
{ "day" : "2010/01/13", "tags" : { "soda" : 5, "php" : 2 } }

我只能实现:

{ "tags" : [ "python", "winter", "nosql" ], "counts" : [ 6, 4, 15 ], "day" : "2010/01/14" }
{ "tags" : [ "soda", "php" ], "counts" : [ 5, 2 ], "day" : "2010/01/13" }

使用:

db.test.aggregate({"$unwind" : "$tags"}, {"$group" : {"_id" : {"day" : "$day", "tags" : "$tags"}, "count" : {"$sum" : 1}}}, {"$group" : {"_id" : "$_id.day", "tags" : {"$push" : "$_id.tags"}, "counts" : {"$push" : "$count"}}}, {"$project" : {"day" : "$_id", "_id" : 0, "tags" : 1, "counts" : 1}}, {"$sort" : {"day" : -1}}, {"$limit" : 2})

似乎我需要像" $ addToSubdocument" :{"子文档" :{" $ key" :" $ value"}}能够将我的标签及其值推送到我的"标签中#34; subocument,或者我只是想错一些小事?

1 个答案:

答案 0 :(得分:0)

在MongoDB聚合框架中,您不能将值用作键。从您想要的输出中可以看出,您打算这样做。

但是,借助聚合框架和客户端逻辑,您可以将结果转换为您想要的格式。

e.g。在MongoDB shell中,您可以运行以下查询。 (或任何支持MongoDB驱动程序的语言)

var items = {};

db.test.aggregate([
   {$match: {day:{$lte: "2010/01/14", $gte: "2010/01/13"}}},
   {$unwind: "$tags"},
   {$group:{_id:{ day: "$day", tag: "$tags"}, count: {$sum:1}}},
   {$project:{_id:0, "tag":"$_id.tag", "day":"$_id.day", count:1}},
   {$sort:{day:1}}
]).forEach(function(d){
  var eItem = items[d.day];
  if(eItem != null)
  {
     eItem.tags[d.tag] = d.count;
  }
  else
  {
    var item = {};
    item.day = d.day;
    item.tags = {};
    item.tags[d.tag] = d.count;
    items[d.day]=item;
  }
});

printjson(items);

输出将是:

{ 
    "2010/01/13" : {
        "day" : "2010/01/13", 
        "tags" : {
            "soda" : 5, 
            "php" : 2
        }
    }, 
    "2010/01/14" : {
        "day" : "2010/01/14", 
        "tags" : {
            "nosql" : 15, 
            "winter" : 4, 
            "python" : 6
        }
    }
}