mongodb如何聚合之后返回整条数据呢?

如下:

经过过滤后,再分组,两个字段为分组条件。
但是,我只想获取分组内时间,即fdate为最大的那条数据
如何能做到??

db.SEC_2018_05_12.aggregate([{ $match : { fyear : { $eq : 2018},fmonth:{$eq : 5},fday:{$eq : 12},fhour:{$eq : 17},fmin:{$eq : 8} } }
    ,  { $group: { _id: {dev_id: "$dev_id", data_id: "$data_id"},maxTimeValue: { $max: "$fdate" } } }  ]).pretty()
阅读 3.2k
1 个回答

如果能给些测试条件别人会更容易理解你的问题。
首先说$eq,这个运算符大部分时候没有必要写。所以你的查询等价于:

db.SEC_2018_05_12.aggregate([
    { $match : { fyear : 2018, fmonth: 5, fday: 12, fhour: 17, fmin: 8 } }, 
    { $group: { _id: {dev_id: "$dev_id", data_id: "$data_id"}, maxTimeValue: { $max: "$fdate" } } }  ]).pretty()

然后你的要求是取到第一条数据,而不仅仅是最大那个fdate值。可以换个思路来理解这个问题:

按dev_id asc, data_id asc, fdate desc三者来排序,然后取每个分组的第一条数据

按照这个思路,查询应该是:

db.SEC_2018_05_12.aggregate([
    { $match : { fyear : 2018, fmonth: 5, fday: 12, fhour: 17, fmin: 8 } }, 
    { $sort: { dev_id: 1, data_id: 1, fdate: -1} },
    { $group: { _id: {dev_id: "$dev_id", data_id: "$data_id"}, maxDoc: { $first: "$$ROOT" } } }  ]).pretty()

最后说说数据模型设计的问题。$match这里其实就是一个时间,但是被你拆成了很多部分来存储。除非有明确的理由支持,个人并不是十分赞成这样的做法。

  1. 本来一个时间只有4 bytes,你这么一来变成了5 x 4 = 20 bytes,注意存储空间;
  2. $match/$sort需要索引的支持,所以原来一个索引现在将会变成5个字段的联合索引,同样是浪费空间和效率;

在数据量大的情况下,上面的查询是需要索引支持的。换你现在的写法,索引应该是:

{
  fyear: 1,
  fmonth: 1,
  fday: 1,
  fhour: 1,
  fmin: 1,
  dev_id: 1,
  data_id: 1,
  fdate: -1
}

看上去就够惊悚了不是吗?但其实前面那一堆时间本身只是一个时间而已。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进