Scala Slick 3.0.1 Отношение к себе

У меня есть сущность под названием «Категория», которая имеет отношение к самой себе. Существует два типа категорий: родительская категория и подкатегория. Подкатегории имеют в атрибуте idParent идентификатор из родительской категории.

Я определил схему таким образом

class CategoriesTable(tag: Tag) extends Table[Category](tag, "CATEGORIES") {

  def id = column[String]("id", O.PrimaryKey)
  def name = column[String]("name")
  def idParent = column[Option[String]]("idParent")

  def * = (id, name, idParent) <> (Category.tupled, Category.unapply)
  def categoryFK = foreignKey("category_fk", idParent, categories)(_.id.?)
  def subcategories = TableQuery[CategoriesTable].filter(_.id === idParent)
}

И у меня есть эти данные:

   id      name      idParent
------------------------------
 parent   Parent
 child1   Child1      parent
 child2   Child2      parent

Теперь я хочу получить результат на карте, сгруппированной по родительской категории, например

Map(
 (parent,Parent,None) -> Seq[(child1,Child1,parent),(child2,Child2,parent]
)

Для этого я попытался выполнить следующий запрос:

def findChildrenWithParents() = {
  db.run((for {
   c <- categories
   s <- c.subcategories
  } yield (c,s)).sortBy(_._1.name).result)
}

Если в этот момент я выполняю запрос с помощью:

categoryDao.findChildrenWithParents().map {
  case categoryTuples => categoryTuples.map(println _)
}

Я получаю это:

(Category(child1,Child1,Some(parent)),Category(parent,Parent,None))
(Category(child2,Child2,Some(parent)),Category(parent,Parent,None))

Тут есть два факта, которые меня уже смутили:

  1. Он возвращает Future[Seq[Category, Category]] вместо Future[Seq[Category, Seq[Category]]], как я и ожидал.
  2. Порядок инвертирован, я ожидаю, что родитель появится первым, например:

    (Категория(родительский,Родительский,Нет),Категория(дочерний1,Дочерний1,Некоторый(родительский))) (Категория(родительский,Родительский,Нет),Категория(дочерний2,Дочерний2,Некоторые(родительский)))

Сейчас попробую их сгруппировать. Поскольку у меня проблемы с вложенными запросами в Slick. Я выполняю группу по результату следующим образом:

categoryDao.findChildrenWithParents().map {
    case categoryTuples => categoryTuples.groupBy(_._2).map(println _)
}

Но результат действительно беспорядок:

(Category(parent,Parent,None),Vector((Category(child1,Child1,Some(parent)),Category(parent,Parent,None),(Category(child2,Child2,Some(parent)),Category(parent,Parent,None))))

Я бы ожидал:

(Category(parent,Parent,None),Vector(Category(child1,Child1,Some(parent)),Category(child2,Child2,Some(parent))))

Не могли бы вы помочь мне с перевернутым результатом и с группой?

Заранее спасибо.


person Alberto Almagro    schedule 02.09.2015    source источник
comment
Я изменил условие подкатегорий на: def subcategories = TableQuery[CategoriesTable].filter(c => id === c.idParent) И теперь у меня проблема только с повторением Parent в группе по результату. Может ли кто-нибудь сказать мне, как я могу избавиться от родителя после группы?   -  person Alberto Almagro    schedule 03.09.2015


Ответы (1)


Хорошо, мне удалось исправить это самостоятельно. Вот ответ, если кто-то хочет узнать из него:

  def findChildrenWithParents() = {
    val result = db.run((for {
     c <- categories
     s <- c.subcategories
    } yield (c,s)).sortBy(_._1.name).result)

    result map {
      case categoryTuples => categoryTuples.groupBy(_._1).map{
        case (k,v) => (k,v.map(_._2))
      }
    }

  }

Решение не идеально. Я хотел бы создать группу уже в Slick, но это дает то, что я хотел.

person Alberto Almagro    schedule 04.09.2015
comment
Только что добавил дополнительную запись для этого albertoalmagro.com/en/ scala-slick-3-отношение к себе - person Alberto Almagro; 07.09.2015
comment
была аналогичная проблема. мои данные, однако, древовидные, а не двухслойные, как у вас. к сожалению, это невозможно сделать с помощью slick, даже ваше решение не сработает в моем случае. мое решение - использовать собственный рекурсивный оператор SQL (MySQL). - person noru; 22.09.2015