Ich versuche Slick zu verwenden, um eine Viele-zu-viele-Beziehung abzufragen, aber ich stoße auf eine Reihe von Fehlern, die am meisten hervorstechen: "Weiß nicht wie zum Auspacken (User, Skill) zu T und packen zu G ".Scala Slick: Probleme mit groupBy und fehlenden Shapes
Die Struktur der Tabellen ist ähnlich der folgenden:
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)
}
Letztlich, was ich will ist
etwas von der FormSELECT 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
erreichen, aber bevor ich verbringe die Zeit zu bekommen versuchen, group_concat, um auch zu arbeiten, habe ich versucht, die einfachere Abfrage zu produzieren (die ich glaube, dass noch gültig ist ...)
SELECT u.* FROM user_skill us, users u, skills s WHERE us.skillId = s.id && us.userId = u.id GROUP BY u.id
ich eine Vielzahl von scala Code versucht haben, diese Abfrage zu produzieren, aber ein Beispiel dafür, was oberhalb der Formfehler verursacht, ist
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.first }
In ähnlicher Weise erzeugt die folgenden ein Packfehler in Bezug auf „User“ statt „(Benutzer, Geschicklichkeit)“
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.map(_._1).first }
Wenn jemand irgendwelche Vorschläge hat, wäre ich sehr dankbar: ich habe die meisten von heute und gestern verbrachte Scheuern google/google Gruppen sowie die Slick-Quelle, aber ich habe nicht eine Lösung noch.
(Auch ich bin mit postgre so Group_concat tatsächlich string_agg wäre)
EDIT
So scheint es, wie wenn groupBy verwendet wird, wird die abgebildete Projektion angewendet, da so etwas wie
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s)).map(_._1)
funktioniert gut, weil _._ 1 gibt den Typ Benutzer, die eine Shape seit Benutzer hat, ist eine Tabelle. Wenn wir jedoch xs.first aufrufen (wie wir es tun, wenn wir groupBy aufrufen), erhalten wir tatsächlich einen zugeordneten Projektionstyp (User, Skill), oder wenn wir map (_._ 1) zuerst anwenden, erhalten wir den Typ User, was ist nicht Benutzer! Soweit ich das beurteilen kann, gibt es keine Form mit Benutzer als Mischtyp, da die einzigen definierten Formen für Shape [Spalte [T], T, Spalte [T]] und für eine Tabelle T < sind: TableNode, Shape [T , NothingContainer # TableNothing, T] wie in slick.lifted.Shape definiert. Außerdem, wenn ich etwas tun, wie
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s))
.groupBy(_._1.id)
.map { case (_, xs) => xs.map(_._1.id).first }
bekomme ich einen seltsamen Fehler in der Form „NoSuchElementException: Schlüssel nicht gefunden: @ 1515100893“, wo die Zifferntaste Wert jedes Mal ändert. Dies ist nicht die Frage, die ich möchte, aber es ist trotzdem ein seltsames Problem.
Ich schrieb eine direkte Abfrage in einer Situation, wenn ich mehrere Tabellen verbinden musste. Eine bessere performante Variante (vorausgesetzt, dass u.id, s.id, us.userId und us.skillId Schlüssel sind) könnte übrigens sein: "SELECT u. *, Group_concat (s.name) FROM user_skill us JOIN Fähigkeiten s ON us.skillId = s.id JOIN Benutzer u ON us.userId = u.id GROUP BY u.id " – Ashalynd
Wie auch immer, wenn Sie gruppieren, erhalten Sie eine Karte (ID -> Liste ((u, s)) und das ist nicht genau wie es in deinem {case} Ausdruck beschrieben ist. – Ashalynd