Как поместить данные из разных таблиц в отдельные списки одним запросом - PullRequest
2 голосов
/ 22 мая 2019

Например, у меня есть какая-то сущность. Каждая сущность имеет несколько атрибутов. БД выглядит примерно так:

 entity                entity_attribute
╔════╦════════╗       ╔════╦════════════╦═══════════╗
║ id ║ name   ║       ║ id ║ entity_id  ║ attribute ║
╠════╬════════╣       ╠════╬════════════╬═══════════╣
║ 1  ║  One   ║       ║ 1  ║ 1          ║ "aaa"     ║ 
║ 2  ║  Two   ║       ║ 2  ║ 1          ║ "bbb"     ║
║ 3  ║  Three ║       ║ 3  ║ 1          ║ "ccc"     ║
╚════╩════════╝       ║ 4  ║ 1          ║ "ddd"     ║
                      ║ 5  ║ 2          ║ "aa"      ║
                      ║ 6  ║ 2          ║ "bb"      ║
                      ╚════╩════════════╩═══════════╝

Мои модели выглядят так:

case class Entity(id: Long, name: String)

case class Entityattribute(id: Long, entityId: Long, attribute: String)

И я пытаюсь получить права с атрибутами ( Важно: без объединения ) через doobie:

(for {
      entitites <- sql"select id, name from entity"query[Entity].to[List]
      attributes <- (sql"select id, entity_id, attribute from entity_attribute where " ++ 
                    Fragments.in(
                      fr"entity_id", 
                      NonEmptyList.fromListUnsafe(entities.map(_.id)))   //Unsafe, just example
                    ).query[EntityAttribute].to[List]
      } yield entitites ++ attributes).transact(xa)

Результат равен одному List[Product]:

List(
  Entity(1, One),
  Entity(2, Two),
  Entity(3, Three),
  EntityAttribute(1,1,"aaa"),
  EntityAttribute(2,1,"bbb"),
  EntityAttribute(3,1,"ccc"),
  EntityAttribute(4,1,"ddd"),
  EntityAttribute(5,2,"aa"),
  EntityAttribute(6,2,"bb")
)

Как изменить запрос doobie для получения результата в два отдельных List[Entity] и List[EntityAttribute]?

1 Ответ

3 голосов
/ 22 мая 2019

Списки в Scala однородны, это означает, что компилятор попытается найти верхнюю границу для типов всех объектов в списке.

Для вашего случая верхняя граница для Entity и EntityAttribute равна Product.

Чтобы сохранить исходные типы, вы можете просто вернуть кортеж, содержащий два списка: List[Entity] и List[EntityAttribute].

} yield (entitites, attributes)).transact(xa)

Тогда вы можете получить списки, просто сопоставив шаблоны по кортежу:

result.map {
   case (entities, attributes) => /* do something */
}
...