Slick 3.0 Viele-zu-Viele-Abfrage mit dem Join als iterierbares

Ich habe mit Slick 3.0 eine Many-to-Many-Sammlung erstellt, aber ich habe Schwierigkeiten, Daten so abzurufen, wie ich es möchte.

Es gibt eine Beziehung zwischen Ereignissen und Interessen. Hier sind meine Tische:

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)
  }
}

Hier ist 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]
}

Und endlich Interessen:

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)
  }
}

Ich kann Tupel von (event.name, interest) mit folgendem Befehl abfragen und abrufen:

val eventInterestQuery = for {
  event <- EventQueries.query
  interest <- event.interests
} yield (event.title, interest.name)

Await.result(db.run(eventInterestQuery.result).map(println), Duration.Inf)

So ist das, was ich derzeit habe.

Was ich möchte, ist in der Lage zu sein, eine Fallklasse zu füllen wie:

case class EventDao(title: String,
                interests: Seq[InterestDao],
                id: Option[Int] = None)

Das Problem ist, dass wenn ich meine Fallklasse wie folgt aktualisiere, mein @ durcheinander gebracht wirdef * Projektion inEventsTable. Außerdem muss ich das @ umbenennEventsTable.interests Filter auf etwas wieEventsTable.interestIds Das ist ein bisschen hässlich, aber ich könnte damit leben, wenn nötig.

Auch ich kann keinen Weg finden, ein @ zu schreibfor Abfrage, die @ ergi(event.name, Seq(interest.name)). Wie auch immer, das ist nur ein Sprungbrett für mich, in der Lage zu sein, ein @ zu geb(EventDao, Seq(InterestDao)) Tupel, das ist, was ich wirklich zurückgeben möchte.

Weiß jemand, wie ich diese Dinge erreichen kann? Ich möchte auch in der Lage sein, eine bestimmte Anzahl von Interessen zu "übernehmen", so dass für einige Abfragen alle zurückgegeben würden, für andere jedoch nur die ersten 3.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage