【问题标题】:MongoDB aggregate queryMongoDB 聚合查询
【发布时间】:2017-06-24 05:50:01
【问题描述】:

在 MongoDB 中我有一个集合:

Statistics
{
    UserID:  int          //User id
    Url: string           //Url
    Clicks: [DateTime]    //A time array    
}

当用户点击一个 url 时,在 Clicks 数组中添加一个点击日期的日期。我的问题是如何编写聚合查询,例如获取从 [date1] 到 [date2] 的点击次数并按 UserID 分组?如何将, 输出到文件?

谢谢!

【问题讨论】:

  • 您的意思是“组”是指对行进行分组,还是指“组”是按用户 ID 排序,这样一个用户 ID 的所有 url 都在结果集中的同一区域中?
  • 我的意思是组与排序不同。就像 SQL 命令 GROUP BY。
  • 我认为您的一些架构在这里丢失了,因为:“获得从 [date1] 到 [date2] 的点击次数”但您没有数字,您的 Clicks 字段不是 Datetime 字段显示点击的整数字段,之后您只有 URL 字段。您的日期字段的名称是什么?
  • Sammaye,该字段的名称是 Clicks。点击次数 - 它是 Clicks 数组中项目的长度。
  • 这是一个非常奇怪的架构。通常,在这种情况下,每次点击都会制作一个文档。嗯,这确实让您变得更加困难,因为您要在许多文档中的子文档中的许多元素中绑定日期时间范围......我会玩一下。

标签: mongodb output aggregation-framework


【解决方案1】:

假设你有这样的数据(见底部如何生成):

{ "_id": ObjectId("508ab0e27bb16229520c9561"), "userid": 0, "url": "", "clickDate": ISODate("20120101T12:01:00Z") }
{ "_id": ObjectId("508ab0e27bb16229520c9562"), "userid": 1, "url": "", "clickDate": ISODate("20120202T12:01:00Z") }
{ "_id": ObjectId("508ab0e27bb16229520c9563"), "userid": 2, "url": "", "clickDate": ISODate("20120303T12:01:00Z") }
{ "_id": ObjectId("508ab0e27bb16229520c9564"), "userid": 3, "url": "", "clickDate": ISODate("20120404T11:01:00Z") }
{ "_id": ObjectId("508ab0e27bb16229520c9565"), "userid": 4, "url": "", "clickDate": ISODate("20120505T11:01:00Z") }

这里是聚合函数:

db.test.aggregate( {
                      $match: {
                        clickDate: { $gte: new Date(2012,8,30,12,0,0) }
                      }
                    },
                    {
                      $group: {
                        _id: "$userid",
                        clicks: { $sum: 1 }
                      }
                    }
                 );

确保$match$group 之前。见early filtering

结果:

{
  "result": [
    { "_id": 8,
      "clicks": 1
    },
    { "_id": 7,
      "clicks": 2
    },
    { "_id": 6,
      "clicks": 2
    },
    { "_id": 3,
      "clicks": 2
    },
    { "_id": 2,
      "clicks": 2
    },
    { "_id": 1,
      "clicks": 2
    },
    { "_id": 4,
      "clicks": 2
    },
    { "_id": 0,
      "clicks": 2
    },
    { "_id": 5,
      "clicks": 2
    },
    { "_id": 9,
      "clicks": 1
    }
  ],
  "ok": 1
}

数据是通过这个循环生成的:

// d=days, m=months (for ISODate months start from 0, while days from 1) 
for (var i = 0, d = 1, m = 0, id = 0; i < 100; i++, d++, m++, id++) {
  if (d > 30){
    d=1;
  }
  if (m > 10){
    m=0;
  }
  if (id > 9){
    id=0;
  }
  db.test.insert({userid: id, url:"", clickDate: new Date(2012,m,d,12,1,0)});
}

【讨论】:

  • 不幸的是,如 cmets 中所述,他的日期实际上是一个数组,所以他想在他的文档中匹配一个数组中的日期,然后 $unwind 那些(最有可能)然后计算匹配的金额然后 $group 按用户 ID。基本上 $sum 仅匹配日期数组的日期。
猜你喜欢
  • 2019-06-18
  • 1970-01-01
  • 2021-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-03
  • 2021-06-02
相关资源
最近更新 更多