tl; dr, как превратить IReduceInit в lazy-seq преобразованных значений
У меня есть запрос к базе данных, который дает достаточно большой набор данных для динамического поворота на клиенте (миллион или две строки, 25 атрибутов- нет проблем для современного ноутбука).
Мой (упрощенный) стек должен был вызывать clojure.jdbc, чтобы получить (что я считал ленивым) последовательность строк результата.Я мог бы просто сериализовать это, передав его как тело через связующее ПО ring-json.Была проблема с тем, что ring-json создавал строку ответа в куче, но у него была опция с 0.5.0 для потоковой передачи ответа.
Я обнаружил путем профилирования нескольких случаев сбоев, которые фактически замыкаются.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"]
Однако это реализует весь набор результатов, и в приведенном выше случае я получу все идентификаторы заранее и в памяти.Не проблема для одного, но у меня их обычно много.
План IReduceInit - это то, что я могу уменьшить, если я дам начальное значение, чтобы я мог сделать вывод в функции сокращения ... (thx @amalloy)
(reduce #(println (:cc_id %2)) [] (jdbc/plan ds ["select cc_id from organisation where cc_id = '675192'"]))
675192
nil
... но в идеале я бы хотел превратить этот IReduceInit в ленивую последовательность значений после применения к ним функции преобразования, чтобы я мог использовать их с ring-json и cheshire,Я не вижу очевидного способа сделать это.