Агрегирование данных в ReactiveMongo по дате

Я пытаюсь получить агрегат в ReactiveMongo 0.12 и Play Framework 2.6 (используя коллекции JSON, а не BSON) путем фильтрации дат из коллекции, называемой "посетители". Типичный документ может выглядеть так:

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

Итак, отсюда я хочу объединить эти данные, чтобы получить различные итоговые данные о посетителях, средние значения и т. Д., Сгруппировать по placeId (который идентифицирует место в другой коллекции) и отфильтровать по датам после 15-05-2016.

Я основал это на этом подобном вопросе - без совпадения это работает, но без этого - это не так. Там нет ошибки, но она просто не работает:

  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 ответа

Решение

Я не хочу отвечать на свой вопрос здесь, но теперь, когда я понял это, я действительно хочу разъяснить другим, как это делается с помощью Aggregate. В конечном итоге на этот вопрос было две части.

1) каков синтаксис запроса даты?

Как упомянул @AndriyKuba, и я видел в документации еще не полностью понял; запрос формулируется так:

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

2) как мне сопоставить запрос в совокупности?

Это больше вопрос порядка запроса. Первоначально я пытался использовать сопоставление после группировки и агрегирования данных - что (очевидно) будет только после фильтрации данных. Поскольку я хотел сначала получить диапазон дат, а затем агрегировать эти данные, которые я должен был сопоставить первым - это также означало, что часть синтаксиса должна была соответственно измениться:

  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, так как есть много примеров попыток понять синтаксис и логику.

ISODate это тип Mongodb, и Model.aggregate не приводит аргументы, поэтому "date" -> Json.obj("$gte" -> JsNumber(longDate)) неправильно.

Вам нужно использовать тип, который будет преобразован в ISODateЯ уверен, что это не так JsNumber,

Это BSONDateTime тип вы бы использовали BSON, но вы этого не сделаете.

Согласно документации это должно быть

JsObject с $dateJsNumber поле с отметкой времени (миллисекунды) в качестве значения

Так что решение может быть (я не проверял):

Match(Json.obj("date" -> Json.obj("$gte" -> Json.obj("$date" -> JsNumber(longDate)))))
Другие вопросы по тегам