杜比。编写 .update.withGeneratedKeys() 和 .update.run
Doobie. Compose .update.withGeneratedKeys() and .update.run
参考 问题。
我想在某些条件下插入一些实体。可以插入也可以不插入。如果条件为真,则插入实体。我想在各种表中插入一些其他数据。它看起来像这样:
val q = sql"insert into some_table (some_field) select 42 where ...(some condition)"
val inserts = List(
sql"insert ...",
sql"insert ...",
sql"insert ..."
)
for {
id <- q.update.withGeneratedKeys[Long]("id")
_ <- inserts.reduce(_ ++ _).update.run
} yield id
问题是这无法编译,因为第一个插入是 fs2.Stream
但第二个不是。
我试图用 _ = inserts.reduce
替换 _ <- inserts.reduce...
。该应用程序可以编译,但不会出现第二行中的 inserts
。
UPD
我可能解决这个问题的方法:
...
for {
idOpt <- q.update.withGeneratedKeys[Long]("id").compile.last
_ <- idOpt.fold(0.pure[ConnectionIO])(_ => inserts.reduce(_ ++ _).update.run)
} yield idOpt
这行得通,但恕我直言,这并不漂亮。有更好的方法吗?
执行批量插入的一种方法 - 如果您有类似的数据 - 是使用 updateMany
- see doc:
import doobie._
type PersonInfo = (String, Option[Short])
def insertMany(ps: List[PersonInfo]): ConnectionIO[Int] = {
val sql = "insert into person (name, age) values (?, ?)"
Update[PersonInfo](sql).updateMany(ps)
}
// Some rows to insert
val data = List[PersonInfo](
("Frank", Some(12)),
("Daddy", None))
此外,如果您删除.compile.last
,您可以使用这样一个事实,即如果您的结果 Stream
q.update.withGeneratedKeys[Long]("id")
是 empty
,您 'exit early' for-comprehension
.
总而言之,您可以执行以下操作:
import fs2.Stream
val result =
// Now the for-comprehension operates on a Stream instead of an Option
for {
r <- q.update.withGeneratedKeys[Long]("id")
_ <- Stream.eval(insertMany(data)) // insertMany(data) is defined like in the snippet above
} yield r
result.compile.last
参考
我想在某些条件下插入一些实体。可以插入也可以不插入。如果条件为真,则插入实体。我想在各种表中插入一些其他数据。它看起来像这样:
val q = sql"insert into some_table (some_field) select 42 where ...(some condition)"
val inserts = List(
sql"insert ...",
sql"insert ...",
sql"insert ..."
)
for {
id <- q.update.withGeneratedKeys[Long]("id")
_ <- inserts.reduce(_ ++ _).update.run
} yield id
问题是这无法编译,因为第一个插入是 fs2.Stream
但第二个不是。
我试图用 _ = inserts.reduce
替换 _ <- inserts.reduce...
。该应用程序可以编译,但不会出现第二行中的 inserts
。
UPD
我可能解决这个问题的方法:
...
for {
idOpt <- q.update.withGeneratedKeys[Long]("id").compile.last
_ <- idOpt.fold(0.pure[ConnectionIO])(_ => inserts.reduce(_ ++ _).update.run)
} yield idOpt
这行得通,但恕我直言,这并不漂亮。有更好的方法吗?
执行批量插入的一种方法 - 如果您有类似的数据 - 是使用 updateMany
- see doc:
import doobie._
type PersonInfo = (String, Option[Short])
def insertMany(ps: List[PersonInfo]): ConnectionIO[Int] = {
val sql = "insert into person (name, age) values (?, ?)"
Update[PersonInfo](sql).updateMany(ps)
}
// Some rows to insert
val data = List[PersonInfo](
("Frank", Some(12)),
("Daddy", None))
此外,如果您删除.compile.last
,您可以使用这样一个事实,即如果您的结果 Stream
q.update.withGeneratedKeys[Long]("id")
是 empty
,您 'exit early' for-comprehension
.
总而言之,您可以执行以下操作:
import fs2.Stream
val result =
// Now the for-comprehension operates on a Stream instead of an Option
for {
r <- q.update.withGeneratedKeys[Long]("id")
_ <- Stream.eval(insertMany(data)) // insertMany(data) is defined like in the snippet above
} yield r
result.compile.last