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

Aggregate data in ReactiveMongo matching by date

我正在尝试在 ReactiveMongo 0.12Play Framework 2.6 中进行聚合(使用 JSON collections - 而不是 BSON) 通过从名为 "visitors" 的 collection 中过滤日期。典型的文档可能如下所示:

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

所以从这里我想汇总这些数据以获得各种 visitor 总计、平均值等,按 placeId 分组(标识另一个 collection) 中的位置并按 2016 年 5 月 15 日之后的日期过滤。

我基于此 - 没有 匹配 它可以工作但有它 - 它没有。没有错误,但它不起作用:

  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])

  }

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

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

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

这是一个 BSONDateTime 类型,您会使用 BSON,但您没有。

根据 to documentation 它必须是

JsObject with a $date JsNumber field with the timestamp (milliseconds) as value

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

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

我不想在这里回答我自己的问题,但现在我已经弄明白了,我真的想向其他人澄清这是如何使用 Aggregate 完成的。这个问题最终分为两部分。

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

正如@AndriyKuba 提到的,我在 documentation 中看到但还没有完全理解;查询的格式如下:

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

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

这更多是查询顺序的问题。我最初试图在对数据进行分组和聚合后使用 match - 这(显然)只会在之后过滤数据。因为我想先得到一个日期范围,然后聚合我必须先 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 FrameworkReactiveMongo 的文档,因为有很多实例试图理解语法和逻辑。