Wie verwende ich Column.isin mit Liste?


71
val items = List("a", "b", "c")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items))
          .collect
          .foreach(println)

Der obige Code löst die folgende Ausnahme aus.

Exception in thread "main" java.lang.RuntimeException: Unsupported literal type class scala.collection.immutable.$colon$colon List(a, b, c) 
at org.apache.spark.sql.catalyst.expressions.Literal$.apply(literals.scala:49)
at org.apache.spark.sql.functions$.lit(functions.scala:89)
at org.apache.spark.sql.Column$$anonfun$isin$1.apply(Column.scala:642)
at org.apache.spark.sql.Column$$anonfun$isin$1.apply(Column.scala:642)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33)
at scala.collection.mutable.WrappedArray.foreach(WrappedArray.scala:35)
at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
at scala.collection.AbstractTraversable.map(Traversable.scala:104)
at org.apache.spark.sql.Column.isin(Column.scala:642)

Unten ist mein Versuch, es zu beheben. Es wird kompiliert und ausgeführt, gibt jedoch keine Übereinstimmung zurück. Nicht sicher warum.

val items = List("a", "b", "c").mkString("\"","\",\"","\"")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items))
          .collect
          .foreach(println)

Antworten:


131

Laut Dokumentation isinnimmt ein Vararg, keine Liste. Liste ist hier eigentlich ein verwirrender Name. Sie können versuchen, Ihre Liste wie folgt in vararg zu konvertieren:

val items = List("a", "b", "c")

sqlContext.sql("select c1 from table")
          .filter($"c1".isin(items:_*))
          .collect
          .foreach(println)

Ihre Variante mit mkString wird kompiliert, da ein einzelner String ebenfalls ein vararg ist (mit einer Anzahl von Argumenten gleich 1), aber wahrscheinlich nicht das, was Sie erreichen möchten.


17

So funktionierte es in Java Api (Java 8)

.isin(sampleListName.stream().toArray(String[]::new))));

sampleListName ist eine Liste


5

Spark hat jetzt (seit 2.4.0) eine Methode namens aufgerufen isInCollection, die genau das ist, wonach Sie suchen, anstatt isIn.

(Sollten sie die Methoden nicht vereinheitlichen?)


2

Wie Tomalak es erwähnt hat:

isin(java.lang.Object... list)
A boolean expression that is evaluated to true if the value 
of this expression is contained by the evaluated values of the arguments.

Daher können Sie dieses Problem beheben und die folgende Änderung vornehmen:

val items = List("a", "b", "c").map(c => s""""$c"""")

1
Warum die Karte? Mein ist, dass .filter($"c1".isin(List("a", "b", "c")))das funktionieren würde.
Tomalak

In Anbetracht Ihres Codes List("a", "b", "c").mkString("\"","\",\"","\"")ging ich davon aus, dass Sie jedes Element in doppelte Anführungszeichen setzen möchten. Die Karte macht das Gleiche.
Francis Toth

0

Sogar einfacher:

sqlContext.sql("select c1 from table")
          .filter($"c1".isin("a", "b", "c"))
          .collect
          .foreach(println)

Es sei denn, Sie haben viele Listenwerte, was normalerweise nicht der Fall ist.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.