获取每个Id组的范围内的最后日期

时间:2017-11-02 07:45:47

标签: mongodb mongodb-query aggregation-framework

假设我有一个包含以下项目的集合:

[{myId:0,date:01.01.17,data:1000},
 {myId:1,date:01.02.17,data:2000},
 {myId:0,date:01.03.17,data:3000},
 {myId:1,date:01.04.17,data:4000},
 {myId:0,date:01.05.17,data:5000}]

我想创建一个以日期作为参数的查询,并返回一个包含evrey myId单个对象的数组,其最大日期低于请求的日期。

例如,使用15。03。17日期返回调用查询:

[{myId:1,date:01.02.17,data:2000},
 {myId:0,date:01.03.17,data:3000}]

使用15。01。17日期返回调用查询

[{myId:0,date:01.01.17,data:1000}]

我正在寻找一个不使用db.eval

的答案

1 个答案:

答案 0 :(得分:1)

修复数据以使其有效:

db.junk.insertMany([
 {myId:0,date: new Date("2017-01-01"),data:1000},
 {myId:1,date: new Date("2017-02-01"),data:2000},
 {myId:0,date: new Date("2017-03-01"),data:3000},
 {myId:1,date: new Date("2017-04-01"),data:4000},
 {myId:0,date: new Date("2017-05-01"),data:5000}
])

您运行汇总语句,通过$match过滤条目,然后应用$sort确保订单并在每个分组边界使用$last作为“max”:

db.junk.aggregate([
  { "$match": { "date": { "$lte": new Date("2017-03-15") } } },
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": "$myId",
    "date": { "$last": "$date" },
    "data": { "$last": "$data" }  
  }}
])

返回:

/* 1 */
{
    "_id" : 1.0,
    "date" : ISODate("2017-02-01T00:00:00.000Z"),
    "data" : 2000.0
}

/* 2 */
{
    "_id" : 0.0,
    "date" : ISODate("2017-03-01T00:00:00.000Z"),
    "data" : 3000.0
}

另一个日期:

db.junk.aggregate([
  { "$match": { "date": { "$lte": new Date("2017-01-15") } } },
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": "$myId",
    "date": { "$last": "$date" },
    "data": { "$last": "$data" }  
  }}
])

返回:

/* 1 */
{
    "_id" : 0.0,
    "date" : ISODate("2017-01-01T00:00:00.000Z"),
    "data" : 1000.0
}

如果您真的必须添加$sort作为最后的管道阶段,以确保返回_idmyId值)的顺序:

db.junk.aggregate([
  { "$match": { "date": { "$lte": new Date("2017-03-15") } } },
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": "$myId",
    "date": { "$last": "$date" },
    "data": { "$last": "$data" }  
  }},
  { "$sort": { "_id": 1 } }
])