Doobie返回一个fs2.Stream(doobie.ConnectionIO, String)。如果我们需要将它写入文件,那么显而易见的选项是调用stream.compile.toList.transact(transactor),然后将这个列表保存到文件中。
是否有一种方法可以在不将其转换为list的情况下以流方式保存结果?
发布于 2020-03-06 18:18:32
诀窍是使用cats.IO将doobie.ConnectionIO操作转换为Async[doobie.ConnectionIO].liftIO(IO(...))操作。这样就可以很好地将文件操作与数据库操作结合起来。下面是一个完整的示例程序,它将结果流到文件中。
package com.example
import java.io.BufferedWriter
import better.files.File
import cats.effect._
import cats.implicits._
import doobie._
import doobie.implicits._
import fs2.Stream
object Example extends IOApp {
override def run(args: List[String]): IO[ExitCode] = {
val xa = Transactor.fromDriverManager[IO](
"org.postgresql.Driver", // driver classname
"jdbc:postgresql:example_db", // connect URL (driver-specific)
"postgres", // user
"" // password
)
val drop = sql"drop table if exists example".update.run
val create =
sql"create table if not exists example (id serial primary key, string_value text not null)".update.run
val insert = Update[String]("insert into example (string_value) values (?)")
.updateMany(List("one", "two", "three", "four", "five"))
val setup = for {
_ <- drop.transact(xa)
_ <- create.transact(xa)
_ <- insert.transact(xa)
} yield ()
val select: Stream[doobie.ConnectionIO, String] =
sql"select string_value from example".query[String].stream
val output = writeToFile(select).compile.drain.transact(xa)
for {
_ <- setup
_ <- output
} yield ExitCode.Success
}
private def writeToFile(result: Stream[doobie.ConnectionIO, String]): Stream[doobie.ConnectionIO, Unit] = {
Stream.resource(writer("./example.txt")).flatMap { writer =>
result.intersperse("\n").chunks.evalMap { chunk =>
Async[doobie.ConnectionIO].liftIO(IO(
chunk.foreach(writer.write)
))
}
}
}
private def writer(path: String): Resource[doobie.ConnectionIO, BufferedWriter] = {
Resource.make {
Async[doobie.ConnectionIO].liftIO(IO(
File(path).newBufferedWriter
))
} { outStream =>
Async[doobie.ConnectionIO].liftIO(IO(
outStream.close())
)
}
}
}发布于 2022-01-27 18:12:41
我想这就是你要找的:
import cats.effect.IO
import doobie.implicits._
import doobie.util.transactor.Transactor
import fs2.text
import fs2.io.file.{Files, Path}
object Example {
def queryToFile: IO[Unit] =
sql"select string_value from example"
.query[String]
.stream
.transact(xa)
.through(text.utf8.encode[IO])
.through(Files[IO].writeAll(Path("path-to-file")))
.compile
.drain
}https://stackoverflow.com/questions/60569610
复制相似问题