Próbuję użyć Slicka do sprawdzenia relacji wiele do wielu, ale mam do czynienia z różnymi błędami, z których najważniejsza to "Nie wiem jak rozpakować (User, Skill) do T i spakować do G ".Scala Slick: Problemy z groupBy i brakującymi kształtami
Struktura tabel jest podobny do poniższego:
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)
}
Ostatecznie, co chcę osiągnąć coś formy
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
ale zanim spędzić czas próbuje group_concat do pracy, próbowałem utworzyć prostsze zapytanie (które, jak uważam, jest nadal aktualne ...)
SELECT u.* FROM user_skill us, users u, skills s WHERE us.skillId = s.id && us.userId = u.id GROUP BY u.id
Próbowałem różnych kodu scala do wytworzenia tej kwerendy, ale przykładem tego, co powoduje błąd kształt powyżej
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.first }
Podobnie dodaje produkuje opakowania błąd odnośnie „user” zamiast „(użytkownik, Zręcznościowe)”
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.map(_._1).first }
Jeśli ktoś ma jakieś sugestie, byłbym bardzo wdzięczny: spędziłem większość wczoraj i szorowania grup google/google jak również zręczny źródła, ale nie mam jeszcze rozwiązanie.
(Również używam Postgre tak GROUP_CONCAT byłby rzeczywiście string_agg)
EDIT
Więc wydaje się, gdy jest używany GroupBy, wyznaczoną projekcja zostanie zastosowane, ponieważ coś
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s)).map(_._1)
działa poprawnie, ponieważ _._ 1 daje typ Użytkownicy, którzy mają Kształt, ponieważ Użytkownicy są tabelą. Jednakże, kiedy wywołujemy xs.first (tak jak to robimy, gdy nazywamy groupBy), faktycznie otrzymujemy odwzorowany typ rzutowania (User, Skill), lub jeśli zastosujemy najpierw mapę (_._ 1), otrzymamy typ User, który nie jest Użytkownikiem! O ile wiem, nie ma kształtu z użytkownikiem jako typem mieszanym, ponieważ jedyne zdefiniowane kształty dotyczą kształtu [kolumna [T], T, kolumna [T]] oraz tabeli T <: węzeł tabeli, kształt [T , NothingContainer # TableNothing, T] jak zdefiniowano w slick.lifted.Shape. Ponadto, jeśli zrobię coś podobnego
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s))
.groupBy(_._1.id)
.map { case (_, xs) => xs.map(_._1.id).first }
mam dziwny błąd w postaci „NoSuchElementException: klucz nie został znaleziony: @ 1515100893”, gdzie wartość klucz numeryczny zmienia się za każdym razem. Nie jest to zapytanie, które chcę, ale jest to jednak dziwna kwestia.
Skończyło się na pisaniu bezpośredniego zapytania w sytuacji, gdy musiałem dołączyć do wielu tabel. Nawiasem mówiąc, lepszym wariantem wydajności (pod warunkiem, że u.id, s.id, us.userId i us.skillId są kluczami) mogą być: "SELECT u. *, Group_concat (s.name) FROM user_skill nas DOŁĄCZ DO SKŁADANIA umiejętności s ON us.skillId = s.id JOIN users u ON us.userId = u.id GROUP BY u.id " – Ashalynd
Ale w każdym razie, kiedy grupujesz, dostajesz mapę (id -> lista ((u, s)) i to jest nie dokładnie, jak jest to opisane w twoim {case} wyrażeniu. – Ashalynd