首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Doobie流从数据库保存到文件

将Doobie流从数据库保存到文件
EN

Stack Overflow用户
提问于 2020-03-06 18:18:32
回答 2查看 1.2K关注 0票数 2

Doobie返回一个fs2.Stream(doobie.ConnectionIO, String)。如果我们需要将它写入文件,那么显而易见的选项是调用stream.compile.toList.transact(transactor),然后将这个列表保存到文件中。

是否有一种方法可以在不将其转换为list的情况下以流方式保存结果?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-06 18:18:32

诀窍是使用cats.IOdoobie.ConnectionIO操作转换为Async[doobie.ConnectionIO].liftIO(IO(...))操作。这样就可以很好地将文件操作与数据库操作结合起来。下面是一个完整的示例程序,它将结果流到文件中。

代码语言:javascript
复制
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())
      )
    }
  }
}
票数 3
EN

Stack Overflow用户

发布于 2022-01-27 18:12:41

我想这就是你要找的:

代码语言:javascript
复制
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
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60569610

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档