Slick 3.0 kullanarak çoktan çoğa koleksiyon oluşturdum, ancak istediğim şekilde veri almak için mücadele ediyorum.Slick 3.0 yinelenen birleştirme olarak birleştirme ile çok çok sayıda sorgu
Olaylar ve İlgi Alanları arasında çoktan çoğa bir ilişki var. İşte benim tablolar şunlardır:
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]
}
Ve nihayet İlgi:
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)
}
}
Ben sorgulamak ve aşağıdaki ait dizilerini (event.name, ilgi) alabilirsiniz
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)
}
}
İşte EventsInterests var :
val eventInterestQuery = for {
event <- EventQueries.query
interest <- event.interests
} yield (event.title, interest.name)
Await.result(db.run(eventInterestQuery.result).map(println), Duration.Inf)
Yani bu şu an sahip olduğum şey. Benim istediğim
benzeri bir vaka sınıfını doldurmamız mümkün şudur:
case class EventDao(title: String,
interests: Seq[InterestDao],
id: Option[Int] = None)
sorun böyle benim davam sınıfını güncellemek, eğer EventsTable
benim def *
projeksiyonunu karıştıran biridir olmasıdır. Ayrıca, EventsTable.interests
filtresini biraz çirkin olan EventsTable.interestIds
gibi bir şeye yeniden adlandırmak zorunda kalacağım, ancak gerekirse yaşayabilirim.
Ayrıca, (event.name, Seq(interest.name))
değerini veren bir for
sorgusu yazmanın bir yolunu bulamıyorum. Her neyse, bu sadece bana geri dönmek istediğim bir (EventDao, Seq(InterestDao))
tuple verebilmek için bir atlama taşıdır.
Bu şeyleri nasıl başarabileceğimi bilen var mı? Ayrıca, belirli sayıdaki ilgi alanlarını 'alabilmeyi' istiyorum, bu yüzden bazı sorgular için her şey iade edilebilir, ancak diğerleri için sadece ilk 3 olurdu.
val eventInterestQuery = for {
event <- EventQueries.query
interest <- event.interests
} yield (event, interest)
Await.result(db.run(eventInterestQuery.result
// convert the interests to a sequence.
.map {
_.groupBy(_._1)
.map {
case (k,v) => (k, v.map(_._2))
}.toSeq
}
), Duration.Inf)
Bu delilik, tüm grupta toplanmış sonuç kümesini * telin üzerine * göndermek ve sonra da istemciye gruplamak zorundasınız. Küçük sonuç kümeleri için, büyük bir anlaşma yok, ancak veritabanı düzeyinde kolayca gruplandırılabilen 100K + kayıtları gönderiyor, vay. – virtualeyes
@virtualeyes: o zaman nasıl bir yaklaşım önerirsiniz? – LuGo
@virtualeyes Tam soruyu okumadım ama groupBy doğrudan sorguda kullanılamıyor mu? Belgelerin açıklandığı gibi: http://slick.typesafe.com/doc/3.0.0/queries.html#aggregation – Ixx