0

我试图通过从名为“访问者”的集合中过滤日期来获取ReactiveMongo 0.12Play Framework 2.6中的聚合(使用JSON 集合- 而不是BSON )。典型的文档可能如下所示:

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

因此,我想从这里聚合这些数据以获取各种访问者总数、平均值等,按placeId分组(标识另一个集合中的地点)并按 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])

  }

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

4

2 回答 2

1

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

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

它是BSONDateTime你会使用的类型BSON,但你不会。

根据文档,它必须是

JsObject$date JsNumber时间戳(毫秒)为值的字段

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

Match(Json.obj("date" -> Json.obj("$gte" -> Json.obj("$date" -> JsNumber(longDate)))))
于 2017-09-30T10:43:55.000 回答
0

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

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

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

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

2) 如何匹配Aggregate中的查询?

这更多的是查询顺序的问题。我最初试图在对数据进行分组和聚合之后使用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结合使用的文档,因为有很多尝试理解语法和逻辑的实例。

于 2017-09-30T20:27:00.063 回答