你如何在 DBIOaction SLICK 中展平一个 Sequence of Sequence?

How do you flatten a Sequence of Sequence in DBIOaction SLICK?

大家好,我是 slick 的新手,我该如何展平这个序列?这样就可以 return 注释代码

    def insertIfNotExists(mapCountryStates: Map[String, Iterable[StateUtil]]): Future[Seq[Seq[StateTable]]] /*: Future[Seq[StateTable]]*/ = {
    val interaction = DBIO.sequence(mapCountryStates.toSeq.map { case (alpha2Country, statesUtil) =>
      val codes = statesUtil.map(_.alpha3Code)
      for {
        countryId <- Countries.filter(_.alpha2Code === alpha2Country).map(_.id).result.head
        existing <- States.filter(s => (s.alpha3Code inSet codes) && s.countryId === countryId).result
        stateTables = statesUtil.map(x => StateTable(0L, x.name, x.alpha3Code, countryId))
        statesInserted <- StatesInsertQuery ++= stateTables.filter(s => !existing.exists(x => x.alpha3Code == s.alpha3Code && x.countryId == s.countryId))
      } yield existing ++ statesInserted
    })

    db.run(interaction.transactionally)
  }

如果我写在这里:

val interaction = DBIO.sequence(...).flatten

或此处:

db.run(交互。扁平化。交易)

[错误] 无法证明 Seq[Seq[StateRepository.this.StateTableMapping#TableElementType]] <:< slick.dbio.DBIOAction[R2,S2,E2].

但是当应用程序运行时,因为 IDE 没有将其检测为错误:

我更新我的定义 DBIO.fold:

一个可行的解决方案应该是在 Future 完成后将序列展平:

def insertIfNotExists(mapCountryStates: Map[String, Iterable[StateUtil]]): Future[Seq[StateTable]] = {
  val interaction = DBIO.sequence(mapCountryStates.toSeq.map { case (alpha2Country, statesUtil) =>
    val codes = statesUtil.map(_.alpha3Code)
    for {
      countryId <- Countries.filter(_.alpha2Code === alpha2Country).map(_.id).result.head
      existing <- States.filter(s => (s.alpha3Code inSet codes) && s.countryId === countryId).result
      stateTables = statesUtil.map(x => StateTable(0L, x.name, x.alpha3Code, countryId))
      statesInserted <- StatesInsertQuery ++= stateTables.filter(s => !existing.exists(x => x.alpha3Code == s.alpha3Code && x.countryId == s.countryId))
    } yield existing ++ statesInserted
  })

  db.run(interaction.transactionally).map(_.flatten)
}

看起来您可能在 DBIO.fold 之后。这提供了一种方法来采取一些行动并将它们减少到一个单一的价值。在这种情况下,您的单个值是来自 Seq[Seq[StateTable]].

Seq[StateTable]

草图大概是这样的……

def insertIfNotExists(...): DBIO[Seq[StateTable]] = {
  val interaction: Seq[DBIO[Seq[StateTable]]] = ...
  val startingPoint: Seq[StateTable] = Seq.empty
  DBIO.fold(interaction, startingPoint) {
    (total, list) => total ++ list
  }
}

看起来类型将使用折叠排列。希望对你有用。

Chapter 4 of Essential Slick 中有更多关于折叠的信息。