12

Slick を使用して多対多の関係を照会しようとしていますが、さまざまなエラーが発生しています。 G」。

テーブルの構造は次のようになります。

case class User(val name: String, val picture: Option[URL], val id: Option[UUID])
object Users extends Table[User]("users") {
  def name = column[String]("name")
  def picture = column[Option[URL]]("picture")
  def id = column[UUID]("id")
  def * = name ~ picture ~ id.? <> (User, User.unapply _)
}

case class Skill(val name: String, val id: Option[UUID])
object Skills extends Table[Skill]("skill") {
  def name = column[String]("name")
  def id = column[UUID]("id")
  def * = name ~ id.? <> (Skill, Skill.unapply _)
}

case class UserSkill(val userId: UUID, val skillId: UUID, val id: Option[UUID])
object UserSkills extends Table[UserSkill]("user_skill") {
  def userId = column[UUID]("userId")
  def skillId = column[UUID]("skillId")
  def id = column[UUID]("id")
  def * = userId ~ skillId ~ id.? <> (UserSkill, UserSkill.unapply _)
  def user = foreignKey("userFK", userId, Users)(_.id)
  def skill = foreignKey("skillFK", skillId, Skills)(_.id)
}

最終的に、私が達成したいのは、形の何かです

SELECT u.*, group_concat(s.name) FROM user_skill us, users u, skills s WHERE us.skillId = s.id && us.userId = u.id GROUP BY u.id

しかし、 group_concat を機能させるために時間を費やす前に、より単純なクエリを作成しようとしました (これはまだ有効だと思います...)。

SELECT u.* FROM user_skill us, users u, skills s WHERE us.skillId = s.id && us.userId = u.id GROUP BY u.id

このクエリを生成するためにさまざまな scala コードを試しましたが、上記の形状エラーの原因の例は次のとおりです。

(for {
  us <- UserSkills
  user <- us.user
  skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.first }

同様に、以下は「(User, Skill)」ではなく「User」に関するパッキング エラーを生成します。

(for {
  us <- UserSkills
  user <- us.user
  skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.map(_._1).first }

誰か提案があれば、私は非常に感謝しています.今日と昨日のほとんどを google/google グループと洗練されたソースを精査することに費やしましたが、まだ解決策がありません.

(また、postgre を使用しているため、group_concat は実際には string_agg になります)

編集

したがって、 groupBy が使用されると、マップされた射影が適用されるように見えます。

(for {
  us <- UserSkills
  u   <- us.user
  s   <- us.skill
} yield (u,s)).map(_._1)

_._1 は、Users がテーブルであるため、Shape を持つタイプ Users を与えるため、正常に動作します。ただし、xs.first を呼び出すと (groupBy を呼び出すときと同じように)、実際にはマップされたプロジェクション タイプ (User、Skill) が返されます。または、最初に map(_._1) を適用すると、タイプ User が取得されます。これはユーザーではありません。私が知る限り、定義されている唯一の形状は Shape[Column[T], T, Column[T]] とテーブル T <: TableNode, Shape[T 、NothingContainer#TableNothing、T] slick.lifted.Shape で定義されています。さらに、次のようなことをすると

(for {
  us <- UserSkills
  u   <- us.user
  s   <- us.skill
} yield (u,s))
  .groupBy(_._1.id)
  .map { case (_, xs) => xs.map(_._1.id).first }

「NoSuchElementException: key not found: @1515100893」という形式の奇妙なエラーが発生し、数値キーの値が毎回変化します。これは私が望むクエリではありませんが、奇妙な問題です。

4

2 に答える 2

1

これを試して。あなたが期待した結果が得られることを願っています。ケースクラスの下にある Slick Code を見つけます。

浮き彫りについてはこちら を参考にしてください。

case class User(val name: String, val picture: Option[URL], val id: Option[UUID])
            class Users(_tableTag: Tag) extends Table[User](_tableTag,"users") {
              def name = column[String]("name")
              def picture = column[Option[URL]]("picture")
              def id = column[UUID]("id")
              def * = name ~ picture ~ id.? <> (User, User.unapply _)
            }
             lazy val userTable = new TableQuery(tag => new Users(tag))

            case class Skill(val name: String, val id: Option[UUID])
            class Skills(_tableTag: Tag) extends Table[Skill](_tableTag,"skill") {
              def name = column[String]("name")
              def id = column[UUID]("id")
              def * = name ~ id.? <> (Skill, Skill.unapply _)
            }
             lazy val skillTable = new TableQuery(tag => new Skills(tag))

            case class UserSkill(val userId: UUID, val skillId: UUID, val id: Option[UUID])
            class UserSkills(_tableTag: Tag) extends Table[UserSkill](_tableTag,"user_skill") {
              def userId = column[UUID]("userId")
              def skillId = column[UUID]("skillId")
              def id = column[UUID]("id")
              def * = userId ~ skillId ~ id.? <> (UserSkill, UserSkill.unapply _)
              def user = foreignKey("userFK", userId, Users)(_.id)
              def skill = foreignKey("skillFK", skillId, Skills)(_.id)
            }
             lazy val userSkillTable = new TableQuery(tag => new UserSkills(tag))






(for {((userSkill, user), skill) <- userSkillTable join userTable.filter on
                    (_.userId === _.id) join skillTable.filter on (_._1.skillId === _.id)
                } yield (userSkill, user, skill)).groupBy(_.2.id)
于 2015-02-12T13:39:58.597 に答える