Преобразование/переупаковка результатов запроса Slick

У меня есть, надеюсь, простой вопрос о Слике. Извиняюсь, если это хорошо задокументировано - возможно, я что-то упустил из виду при поиске.

У меня есть совокупный запрос, построенный следующим образом:

def doQuery(/* ... */) = for {
  a <- Query(TableA)
  b <- a.relationship.where // ...
  c <- b.relationship.where // ...
} yield (a, b, c)

Это возвращает мне Query[(A, B, C)].

У меня также есть класс case:

case class Aggregate(a: A, b: B, c: C)

Я хотел бы преобразовать свой запрос в Query[Aggregate], чтобы мои коллеги-разработчики могли вызывать .list() или .firstOption() и получать List или Option в зависимости от ситуации.

Естественно, я выбрал метод .map() для Query, но у него есть неявный аргумент Shape, с которым я не знаю, как обращаться.

Это просто в Slick? В настоящее время мы используем версию 1.0.1, но также возможно обновление до версии 2.0.

С наилучшими пожеланиями,

Дэйв


person davegurnell    schedule 22.10.2013    source источник


Ответы (2)


После долгих экспериментов я пришел к выводу, что в Slick 1 это невозможно.

В Slick 2 вы можете использовать оператор <> для преобразования проекции, собранной в части yield for comprehension:

def doQuery(/* ... */) = for {
  a <- Query(TableA)
  b <- a.relationship.where // ...
  c <- b.relationship.where // ...
} yield (a, b, c) <> (Aggregate.tupled, Aggregate.unapply)

Это работает, как и ожидалось, в сочетании с .list и .firstOption. Я не уверен, каковы последствия попыток использовать .insert, .update и .delete.

person davegurnell    schedule 24.10.2013

Если вы можете изменить doQuery, то вы просто хотите сделать yield Aggregate(a, b, c) вместо yield (a, b, c).

Или, если вы хотите преобразовать результат без изменения doQuery, вы можете вызвать .map { case (a, b, c) => Aggregate(a, b, c) } для результата doQuery.

person pheaver    schedule 23.10.2013
comment
Боюсь, это не сработает. Значения, извлеченные из монад запроса в for comprehension, на самом деле являются псевдонимами таблиц, а не записями, проанализированными из результата запроса. - person davegurnell; 24.10.2013
comment
Дополнительное примечание для ясности... ваше решение будет работать после вызова .list или .firstOption в запросе. В этот момент вы имеете дело с результатом запроса List или Option, а не с Query, поэтому все ведет себя именно так, как ожидалось. - person davegurnell; 24.10.2013