scala - Slick 3.0 many-to-many query with the join as an iterable -
i've created many-to-many collection using slick 3.0, i'm struggling retrieve data in way want.
there many-to-many relationship between events , interests. here tables:
case class eventdao(title: string, id: option[int] = none) class eventstable(tag: tag) extends table[eventdao](tag, "events") { def id = column[int]("event_id", o.primarykey, o.autoinc) def title = column[string]("title") def * = ( title, id.?) <> (eventdao.tupled, eventdao.unapply) def interests = eventinterestqueries.query.filter(_.eventid === id) .flatmap(_.interestfk) } object eventqueries { lazy val query = tablequery[eventstable] val findbyid = compiled { k: rep[int] => query.filter(_.id === k) } }
here's eventsinterests:
case class eventinterestdao(event: int, interest: int) class eventsintereststable(tag: tag) extends table[eventinterestdao](tag, "events_interests") { def eventid = column[int]("event_id") def interestid = column[int]("interest_id") def * = ( eventid, interestid) <> (eventinterestdao.tupled, eventinterestdao.unapply) def eventfk = foreignkey("event_fk", eventid, eventqueries.query)(e => e.id) def interestfk = foreignkey("interest_fk", interestid, interestqueries.query)(i => i.id) } object eventinterestqueries { lazy val query = tablequery[eventsintereststable] }
and interests:
case class interestdao(name: string, id: option[int] = none) class intereststable(tag: tag) extends table[interestdao](tag, "interests") { def id = column[int]("interest_id", o.primarykey, o.autoinc) def name = column[string]("name") def name_idx = index("idx_name", name, unique = true) def * = ( name, id.?) <> (interestdao.tupled, interestdao.unapply) def events = eventinterestqueries.query.filter(_.interestid === id) .flatmap(_.eventfk) } object interestqueries { lazy val query = tablequery[intereststable] val findbyid = compiled { k: rep[int] => query.filter(_.id === k) } }
i can query , retrieve tuples of (event.name, interest) following:
val eventinterestquery = { event <- eventqueries.query interest <- event.interests } yield (event.title, interest.name) await.result(db.run(eventinterestquery.result).map(println), duration.inf)
so have.
what want able populate case class like:
case class eventdao(title: string, interests: seq[interestdao], id: option[int] = none)
the trouble if update case class this, messes def *
projection in eventstable
. also, i'll have rename eventstable.interests
filter eventstable.interestids
bit ugly live if necessary.
also, can't find way of writing for
query yields (event.name, seq(interest.name))
. anyway, that's stepping stone me being able yield (eventdao, seq(interestdao))
tuple want return.
does know how can achieve these things? want able 'take' number of interests, queries returned, others first 3 be.
so after reading this page , chatting on mailing list, got working:
val eventinterestquery = { event <- eventqueries.query interest <- event.interests } yield (event, interest) await.result(db.run(eventinterestquery.result // convert interests sequence. .map { _.groupby(_._1) .map { case (k,v) => (k, v.map(_._2)) }.toseq } ), duration.inf)
Comments
Post a Comment