按日期匹配的ReactiveMongo中的聚合数据

时间:2017-09-29 11:41:15

标签: date playframework type-conversion reactivemongo reactivemongo-play-json

我正在尝试使用 ReactiveMongo 0.12 Play Framework 2.6 (使用 JSON集合 - 而不是 BSON )通过从名为“visitor”的集合中过滤日期。典型文档可能如下所示:

{ "_id": ObjectID("59c33152ca2abb344c575152"), "placeId": ObjectID("59c33152ca2abb344c575152"), "date": ISODate("2017-03-26T00:00:00Z"), "visitors": 1200 }

所以从这里我想聚合这些数据以获得各种访客总计,平均值等,按 placeId 进行分组(它标识另一个集合中的地点)并在2016年5月15日之后按日期过滤。

我的基础是这个similar question - 没有匹配它可以工作但没有它 - 它没有。没有错误,但它不起作用:

  def getVisitorAggregate(col: JSONCollection) = {

    import col.BatchCommands.AggregationFramework.{Group, Match, SumField, AvgField, MinField, MaxField}

    val format = new java.text.SimpleDateFormat("dd-MM-YYYY")
    val myDate = "15-05-2016"

    val parseDate: Date = format.parse(myDate)
    val longDate: Long = parseDate.getTime

    col.aggregate(
      Group(JsString("$placeId"))(
        "totalVisitors" -> SumField("visitors"),
        "avgVisitors" -> AvgField("visitors"),
        "minVisitors" -> MinField("visitors"),
        "maxVisitors" -> MaxField("visitors")
      ),
      List(Match(Json.obj("date" -> Json.obj("$gte" -> JsNumber(longDate)))))
    )
      .map(_.head[VisitorAggregate])

  }

我已经在线查看并测试了很多小时,但我找不到正确的语法,但对于知道我确定的人来说这很简单。感谢

2 个答案:

答案 0 :(得分:1)

ISODate是mongodb类型,而Model.aggregate不会转换参数,因此"date" -> Json.obj("$gte" -> JsNumber(longDate))是错误的。

您需要使用将转换为ISODate的类型,我很确定它不是JsNumber

您使用BSONDateTimeBSON类型,但不是。{/ p>

根据to documentation,它必须是

  带有JsObject $date字段的

JsNumber,其中包含时间戳(毫秒)   作为价值

所以解决方案可以(我没有验证):

Match(Json.obj("date" -> Json.obj("$gte" -> Json.obj("$date" -> JsNumber(longDate)))))

答案 1 :(得分:0)

我不想在这里回答我自己的问题,但现在我已经想到了这一点我真的想向其他人澄清如何使用 Aggregate 来完成这项工作。最终这个问题有两个部分。

1)查询日期的语法是什么?

正如@AndriyKuba提到的那样,我在documentation中看到过但尚未完全理解;查询的结构如下:

   Json.obj("date" -> Json.obj("$gte" -> Json.obj("$date" -> JsNumber(longDate))))

2)如何在聚合匹配查询?

这更像是查询顺序的问题。在分组和聚合数据之后,我最初尝试使用 match - 这显然只会过滤后的数据。因为我想首先得到一个日期范围然后聚合那些我必须首先匹配的数据 - 这也意味着一些语法必须相应地改变:

  def getVisitorAggregate(col: JSONCollection) = {

    import col.BatchCommands.AggregationFramework.{Group, Match, SumField, AvgField, MinField, MaxField}

    val format = new java.text.SimpleDateFormat("dd-MM-YYYY")
    val myDate = "15-05-2016"

    val parseDate: Date = format.parse(myDate)
    val longDate: Long = parseDate.getTime

    col.aggregate(
      Match(Json.obj("date" -> Json.obj("$gte" -> Json.obj("$date" -> JsNumber(longDate))))),
      List(Group(JsString("$rstId"))(
        "totalVisitors" -> SumField("visitors"),
        "avgVisitors" -> AvgField("visitors"),
        "minVisitors" -> MinField("visitors"),
        "maxVisitors" -> MaxField("visitors")
      ))
    )
      .map(_.head[VisitorAggregate])

  }

非常令人沮丧的是,没有更多关于将 Play Framework ReactiveMongo 一起使用的文档,因为有很多实例试图理解语法和逻辑。