2017-04-10 2 views
1

Sortierung Ich habe diesen Code Scala aber nicht die sortierte Liste geben:Scala Slick Abfrage nicht

def getItemsByCategoryId(catId: Long, start: Int = 0, limit: Option[Int] = None): Future[Seq[(Item, Seq[String])]] = { 

    val itemList = items.sortBy(_.name).filter(_.categoryId === catId).drop(start) 

    val q = for { 
    (j, pair) <- itemList joinLeft (groups join tags on (_.tagId === _.id)) on (_.id === _._1.itemId) 
    } yield (j, pair) 

    db.run(q.result).map { (row) => 
    row.groupBy(_._1).map { x => 
     val tags = x._2.map(_._2).flatten 
     (x._1, tags.map(_._2.keyword)) 
    }.toSeq 
    } 
} 

Wenn ich nur diese Zeile verwenden unten I der sortierten Liste erhalten

val itemList = items.sortBy(_.name).filter(_.categoryId === catId).drop(start) 

Ist Die Join/GroupBy-Operationen beeinflussen die Sortierung in irgendeiner Weise?

+1

Ja, sie tun und auf eine sehr große Weise. Wenn Sie also die sortierten Ergebnisse möchten, müssen Sie erneut sortieren. –

Antwort

1

TraversableLike.groupBy gibt eine immutable.Map zurück. Die Einfügereihenfolge wird nur für Map-Werte beibehalten, da die Implementierung ihre Elemente in einer for-Schleife iteriert. Schlüssel im Gegenteil haben nicht wirklich eine Bestellung. Sie sind das Ergebnis der gelieferten Funktion.

Die Scala-Standard-Sammlungsbibliothek verfügt nicht über eine Out-of-the-Box-Lösung für dieses Problem. Da ich genau das gleiche Problem hatte, schrieb ich meine eigene orderedGroupBy als Erweiterung Seq, die eine immutable.ListMap stattdessen zurückgibt:

implicit class SeqWithOrderedGroupBy[A](xs: Seq[A]) { 

    /** 
    * Partitions this traversable collection into a map of traversable collections according to some discriminator function. 
    * Preserves insertion order. 
    * 
    * @param f the discriminatior function. 
    * @tparam K the type of keys returned by the discriminator function. 
    * @return An ordered map from keys to seq. 
    */ 
    def orderedGroupBy[K](f: A => K): immutable.ListMap[K, Seq[A]] = { 
    val m = mutable.ListBuffer.empty[(K, mutable.Builder[A, Seq[A]])] 
    for (elem <- xs) { 
     val key = f(elem) 
     val builder = m.find(_._1 == key) 
     .map(_._2) 
     .getOrElse { 
      val bldr = mutable.Seq.newBuilder[A] 
      m.append((key, bldr)) 
      bldr 
     } 

     builder += elem 
    } 
    val b = immutable.ListMap.newBuilder[K, Seq[A]] 
    for ((k, v) <- m) 
     b += ((k, v.result)) 

    b.result 
    } 
} 

Haftungsausschluss: Ich habe nicht die Leistung der oben genannten Schnipsel zu TraversableLike.groupBy vergleichen. Es ist ausreichend für meine Zwecke, aber es könnte schlimmer sein. Verbesserungen sind jedoch willkommen.

+0

Ausgezeichnet - genau das, was ich brauchte, um Scala neu zu sein – srvy

2

GroupBy behält die Reihenfolge nicht bei, da eine Map zurückgegeben wird. Dieses Verhalten entspricht den Scala-Sammlungen.

Verwandte Themen