Sto cercando di utilizzare Slick per eseguire una query di relazione molti-a-molti, ma sto correndo in una varietà di errori, il più importante è "Non so come per decomprimere (Utente, Abilità) in T e comprimere in G ".Scala Slick: problemi con groupBy e forme mancanti
La struttura delle tabelle è simile al seguente:
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)
}
In definitiva, quello che voglio ottenere è una sorta di forma
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
ma prima di spendere il tempo cercando di ottenere group_concat per funzionare, ho cercato di produrre la query più semplice (che credo sia ancora valida ...)
SELECT u.* FROM user_skill us, users u, skills s WHERE us.skillId = s.id && us.userId = u.id GROUP BY u.id
ho provato una varietà di codice scala per produrre questa domanda, ma un esempio di ciò che causa dell'errore forma sopra è
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.first }
Analogamente, quanto segue produce un errore relativo imballaggio "Utente" invece di "(user, Abilità)"
(for {
us <- UserSkills
user <- us.user
skill <- us.skill
} yield (user, skill)).groupBy(_._1.id).map { case(_, xs) => xs.map(_._1).first }
Se qualcuno ha qualche suggerimento, sarei molto grata: ho passato la maggior parte di oggi e di ieri purga gruppi Google/Google e la fonte chiazza di petrolio, ma non ho una soluzione ancora.
(Inoltre, sto usando postgre così group_concat sarebbe in realtà string_agg)
EDIT
Così sembra come quando si usa groupBy, la proiezione mappato viene applicato perché qualcosa di simile
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s)).map(_._1)
funziona correttamente perché _._ 1 fornisce il tipo Utenti, che ha una forma poiché Users è una tabella. Tuttavia, quando chiamiamo xs.first (come facciamo quando chiamiamo groupBy), in realtà otteniamo un tipo di proiezione mappato (User, Skill), o se applichiamo map (_._ 1) per primo, otteniamo il tipo User, che non sono utenti! Per quanto ne so, non c'è forma con Utente come tipo misto perché le uniche forme definite sono per Forma [Colonna [T], T, Colonna [T]] e per una tabella T <: TableNode, Shape [T , NothingContainer # TableNothing, T] come definito in slick.lifted.Shape. Inoltre, se faccio qualcosa di simile
(for {
us <- UserSkills
u <- us.user
s <- us.skill
} yield (u,s))
.groupBy(_._1.id)
.map { case (_, xs) => xs.map(_._1.id).first }
ottengo uno strano errore di forma "NoSuchElementException: chiave non trovato: @ 1.515.100,893 mila", dove il valore tasto numerico cambia ogni volta. Questa non è la domanda che voglio, ma è comunque una strana questione.
Ho finito per scrivere una query diretta in una situazione in cui dovevo unirmi a più tabelle. A proposito, una variante più performante (fornita da u.id, s.id, us.userId e us.skillId sono le chiavi) potrebbe essere: "SELECT u. *, Group_concat (s.name) FROM user_skill us JOIN skills s ON us.skillId = s.id JOIN utenti u ON us.userId = u.id GROUP BY u.id " – Ashalynd
Ma comunque, quando si raggruppa, si ottiene una mappa (id -> Elenco ((u, s)) e questo è non esattamente come è descritto nell'espressione {case}. – Ashalynd