Tuple with many slicks

Many slices are combined:

for { ((((a, b), c), d), e) <- qa.filter(_.m == x) join qb on (_.m === _.id) join qc on (_._1.u === _.uid) join qd.filter(_.rid == uid) on (_._1._1.u === _.aid) joinLeft qe on (_._1._1._1.u === _.uid) } yield (c, d, e) 

few problems:

  • _._._._1 , which continues to grow, has more in common:
  • the ((((a, b), c), d), e) , which makes it difficult to work on which one corresponds to the compound

Question:

How to make it better? Does the code smell you? Really great, if so - which patterns should I use instead?

+5
source share
1 answer

You could write, for example, something like this:

 val query1 = (for { a <- qa filter(_.m === x) b <- qb if am === b.id c <- qc if au === c.uid d <- qd filter(_.rid === uid) if (au === d.aid) } yield (a, c, d)) val query2 = (for { ((a, c, d), e) <- query1 joinLeft qe on (_._1.u === _.uid) } yield (c, d, e)) val results: Future[Seq[(C, D, Option[E])]] = db.run(query2.result) 

In query1 we use implicit inner joins to join the four tables a , b , c and d . Then we can use this query and combine it with another. In your case, the left outer join on table e , which results in query2 . Finally, you execute the resulting query2 in your database. This way you can combine as many queries as you want.

PS: I probably messed up the join conditions in query1 . The principle holds the same.

PPS: In query1 we use monadic unions. The same result can be achieved using applicative compounds. IMHO monastic compounds are preferred since readability is better. He will also save you a few characters. See http://slick.typesafe.com/doc/3.0.0/queries.html for more information on joining and requesting.

To catch up with the question from the comments:

As I said, you can combine as many queries as you want. The script you described might look like this:

 val query1 = (for { a <- qa filter(_.m === x) b <- qb if am === b.id c <- qc if au === c.uid d <- qd filter(_.rid === uid) if (au === d.aid) } yield (a, b, c, d)) val query2 = (for { ((a, b, c, d), e) <- query1 joinLeft qe on (_._1.u === _.uid) } yield (a, b, c, d, e)) val query3 = (for { (a, b, c, d, e) <- query2 f <- qf if //... condition g <- qg if //... condition } yield (a, b, c, d, e, f, g)) val query4 = (for { ((a, b, c, d, e, f, g), i) <- query3 joinLeft qe on (//... condition) } yield (a, b, c, d, e, f, g, i)) 

AFAIK is the only method combining internal and external joins, since there is no such element as a monadic outer join. Applicative joints require left and right sides. For example, queryLeft joinLeft queryRight on ... If queryLeft depends on other joins, you should write this query first.

+5
source

All Articles