Как сохранить дату / время с помощью ReactiveMongo + Play Json в mongodb

Я пытаюсь сохранить java.time.Instant в родном Date формате mongo.

В официальной документации ReactiveMongo указано, что дата и время должны быть сериализованы как

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

введите описание изображения здесь

(http://reactivemongo.org/releases/1.0/documentation/json/overview.html)

Я следую этому правилу, но значение не сохраняется как Date mongo, вместо этого оно сохраняется как обычный документ JSON (BSON):

{
    "_id" : ObjectId("6057b962af0000af00e81ec7"),
    "username" : "john",
    "createdAt" : {
        "$date" : NumberLong(1616361826198)
    }
}

Исходный код Scala, в котором хранится документ:

import play.api.libs.json.Json
import reactivemongo.api.DB
import reactivemongo.api.bson.BSONObjectID
import reactivemongo.api.bson.collection.BSONCollection
import java.time.Instant
import scala.concurrent.{ ExecutionContext, Future }
import reactivemongo.play.json.compat._
import json2bson._
import reactivemongo.api.commands.WriteResult

class Repo(database: DB)(implicit ec: ExecutionContext) {

  def collection: BSONCollection =
    database.collection("users")

  def insertDocument(): Future[WriteResult] = {
    val doc = Json.obj(
      "_id"       -> BSONObjectID.generate(),
      "username"  -> "john",
      "createdAt" -> Json.obj("$date" -> Instant.now().toEpochMilli)
    )

    collection.insert.one(doc)
  }
}

Что здесь не так?

P.S.:

Если я изменю расширенный синтаксис BSON

Json.obj("$date" -> Instant.now().toEpochMilli)

to BSONDateTime:

  ...
  "createdAt" -> BSONDateTime(Instant.now().toEpochMilli)
  ...

оно работает.

Но все же, почему он не работает с расширенным синтаксисом play JSON +?


person Teimuraz    schedule 21.03.2021    source источник
comment
1. Есть несколько примеров расширенного списка рассылки и документации JSON. 2. Кажется, что extended._ отсутствует. 3. Использование JSON в этом случае (для представления внутреннего запроса) не только бесполезно, но и более сложно, а также требует дополнительных затрат из-за конверсий.   -  person cchantep    schedule 22.03.2021


Ответы (1)


Расширенное представление MongoDB JSON не является действующим на сегодняшний день представлением v2. Значение $date должно быть либо форматированной строкой, либо длинным {"$numberLong": "<millis>"}

scala> BSONValue.pretty(implicitly[BSONValue](Json.obj("$date" -> Instant.now().toEpochMilli)))
res12: String =
{
  '$date': NumberLong(1616415630059)
}

scala> BSONValue.pretty(implicitly[BSONValue](Json.obj("$date" -> Instant.now().toString)))
res13: String = ISODate('2021-03-22T12:20:37.571Z')

scala> BSONValue.pretty(implicitly[BSONValue](Json.obj("$date" -> Json.obj("$numberLong" -> Instant.now().toEpochMilli.toString))))
res16: String = ISODate('2021-03-22T12:21:48.843Z')

При этом использование JSON для представления внутреннего запроса (без значения, поступающего как JSON из другого места, например REST API) бесполезно и дорого.

При необходимости убедитесь, что у вас есть весь необходимый импорт (например, extended._).

person cchantep    schedule 22.03.2021