tl;dr IReduceInit を変換された値の遅延シーケンスに変換する方法
クライアントでのライブ ピボット用にかなり大きなデータセットを生成するデータベース クエリがあります (100 万行または 2 行、25 属性 - 最新のラップトップでは問題ありません)。
私の (簡略化された) スタックは、clojure.jdbc を呼び出して、結果行の (怠惰だと思っていた) シーケンスを取得することでした。ring-json ミドルウェアを介して本体として渡すことで、それをシリアル化することができました。ring-json がヒープに応答文字列を構築する際に問題がありましたが、0.5.0 の時点で応答をストリーミングするオプションがあります。
いくつかの失敗ケースのプロファイリングを通じて、実際には clojure.jdbc がメモリ内の結果セット全体を実現してから返すことを発見しました。問題ない!そのライブラリで作業するreducible-query
のではなく、新しい next.jdbc に移動することにしました。
next.jdbc の重要な操作はplan
、クエリを実行して結果セットを取得するために使用できる IReduceInit を返すことです...
(into [] (map :cc_id) (jdbc/plan ds ["select cc_id from organisation where cc_id = '675192'"]))
["675192"]
ただし、これにより結果セット全体が実現され、上記の場合、すべての ID が事前にメモリ内に表示されます。1つでは問題ありませんが、通常はたくさん持っています。
計画 IReduceInit は、開始値を指定すると削減できるものなので、削減関数で出力を行うことができます... (thx @amaloy)
(reduce #(println (:cc_id %2)) [] (jdbc/plan ds ["select cc_id from organisation where cc_id = '675192'"]))
675192
nil
...しかし、理想的には、この IReduceInit を、変換関数を適用した後に値の遅延シーケンスに変換したいので、リング json と cheshire で使用できます。それを行う明白な方法はわかりません。