1

新しいプロジェクト (Scala 2.10.3、Play2 2.2.1、Reactivemongo 0.10.0) で Scala を使い始めたばかりで、MongoDB のすべてのユーザーを外部クライアントにストリーミングする、かなり標準的なユース ケースに遭遇しました。 . Enumerator、Enumeratee API をナビゲートした後、そのための確かな解決策が見つからなかったため、次の方法でこれを解決しました。

    val users = collection.find(Json.obj()).cursor[User].enumerate(Integer.MAX_VALUE, false)
    var first:Boolean = true
    val indexedUsers = (users.map(u => {
        if(first) {
            first = false;
            Json.stringify(Json.toJson(u))
        } else {
            "," + Json.stringify(Json.toJson(u))
        }
    }))

私の観点からすると、これは少し注意が必要です。主な理由は、要素リストに Json 開始配列、Json 終了配列、およびコンマ区切りを追加する必要があり、それを純粋な Json ストリームとして提供できなかったためです。それをストリングスチームに変えました。

そのための標準的な解決策は何ですか?反応中のmongoを使用していますか?

4

1 に答える 1

1

あなたが達成したいことをするヘルパー関数を書きました:

def intersperse[E](e: E, enum: Enumerator[E]): Enumerator[E] = new Enumerator[E] {
  val element = Input.El(e)

  override def apply[A](i1: Iteratee[E, A]): Future[Iteratee[E, A]] = {
    var iter = i1

    val loop: Iteratee[E, Unit] = {
      lazy val contStep = Cont(step)

      def step(in: Input[E]): Iteratee[E, Unit] = in match {
        case Input.Empty ⇒ contStep
        case Input.EOF ⇒ Done((), Input.Empty)
        case e @ Input.El(_) ⇒
          iter = Iteratee.flatten(iter.feed(element).flatMap(_.feed(e)))
          contStep
      }

      lazy val contFirst = Cont(firstStep)

      def firstStep(in: Input[E]): Iteratee[E, Unit] = in match {
        case Input.EOF ⇒ Done((), Input.Empty)
        case Input.Empty ⇒
          iter = Iteratee.flatten(iter.feed(in))
          contFirst
        case Input.El(x) ⇒
          iter = Iteratee.flatten(iter.feed(in))
          contStep
      }

      contFirst
    }

    enum(loop).map { _ ⇒ iter }
  }
}

使用法:

val prefix = Enumerator("[")
val suffix = Enumerator("]")
val asStrings = Enumeratee.map[User] { u => Json.stringify(Json.toJson(u)) }
val result = prefix >>> intersperse(",", users &> asStrings) >>> suffix

Ok.chunked(result)
于 2015-11-20T08:26:40.280 に答える