2016-04-05 16 views
0

Aktuelle Frage ist relativ mit next one, aber jetzt muss ich die Daten aus der Datenbank anstelle von einfügen lesen.slick 3 zwei leftJoin Abfrage Ergebnis zu Klassen Zuordnung

Ich habe nächste drei Fallklassen:

case class A (id: Long, bList: List[B]) 
case class B (id: Long, aId: cList: List[C]) 
case class C (id: Long, bId: Long) 

Und Abfrage mit zwei leftJoin Funktionen und incomingAId zum Filtern aTable Ergebnisse:

val query = (for { 
    ((aResult,bResult),cResult) <- aTable.filter(_.id === incomigAId) 
     .joinLeft(bTable).on(_.id === _.aId) 
     .joinLeft(cTable).on(_._2.map(_.id) === _.bId) 
    } yield ((aResult,bResult),cResult)).result.transactionally 

Nächste Abfrage funktioniert und das Ergebnis sieht gültig, aber isn‘ t einfach zu handhaben, um die Fallklassen. Auch hat executionResultSeq[Nothing] Art und den Prozess der Zuordnung erfordert etwas wie folgt aus:

database.run(query).map{ executionResult => 
    executionResult.map { vectorElement: [Tuple2[Tuple2[A, Option[B]], Option[C]]] 
    ... 
    } 
} 

Gibt es eine richtige Art und Weise Seq [Nichts] (Änderungen in Abfrage) zu verhindern? Oder, wenn der Abfrageergebnis-Typ in Ordnung ist, können Sie die Lösung teilen, wie Sie sie den oben genannten Fallklassen zuordnen?

Antwort

0

Im Moment benutze ich die nächste Lösung, aber ich nehme an, dass ein Teil des Codes optimiert werden kann (z. B. groupBy ersetzt durch etwas anderes).

 execute(query).mapTo[Vector[((A, Option[B]), Option[C])]] 
     .flatMap { insideFuture => 
      insideFuture.groupBy(_._1._1).mapValues { values => 
      //scala groupBy losts ordering 
      val orderedB = values.groupBy(_._1._2).toSeq.sortBy(_._1.map(_.id)).toMap 
      orderedB.mapValues(_.map(_._2)) 
      }.headOption match { 
      case Some(data) => Future.successful { 

       data._1.copy(bList = data._2.map { 
       case (Some(bElement), optionCElements) => 
        bElement.copy(cList = optionCElements.toList.flatten) 

       case _ => 
        throw new Exception("Invalid query result. Unable to find B elements") 
       }.toList) 
      } 
      case None => Future.failed(new Exception("Unable to find A with next id " + incomigAId)) 
      } 
     } 
    }