2015-09-13 5 views
30
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.Spark-Filter isin funktioniert nicht wie erwartet

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 kompiliert und läuft, gibt aber 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) 
+0

Nach [Dokumentation] (https://spark.apache.org/docs/latest/ api/java/org/apache/spark/sql/Spalte.html # isin (java.lang.Objekt ...)) 'isin' nimmt eine Liste, keine Zeichenfolge. – Tomalak

Antwort

57

Laut Dokumentation nimmt isin eine Vararg, kein Liste. Liste ist hier eigentlich ein verwirrender Name. Sie können das Umwandeln Ihrer Liste versuchen, so Vararg:

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

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

Ihre Variante mit mkString kompiliert, weil ein einziger String ist auch ein Vararg (mit Anzahl der Argumente gleich 1), aber es ist proably nicht, was Sie wollen erreichen.

+0

wow, das ist ein verwirrender Mist. Ich habe das an einer Reihe von Orten in Spark bemerkt. Varargs scheinen eher typsicher zu sein, da sie als Any angegeben sind. Wie können wir das reparieren ?! – nont

+0

endlich habe ich das funktioniert! brauchte nur das: _ * ding haha ​​danke! –

+0

@nont Sie haben endlich herausgefunden, warum Spark saugt. Herzliche Glückwünsche! – piggybox

-1

Wie Tomalak hat es erwähnt:

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önnten Sie nur dieses Problem beheben die folgende Änderung vornehmen:

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

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

+0

Betrachtet man den Code 'List (" a "," b "," c "). MkString (" \ "", "\", \ "", "\" ")", ging ich davon aus, dass Sie jeden umschließen wollten Element in doppelten Anführungszeichen. Die Karte macht das Gleiche. –

+0

Nicht mein Code. ;) – Tomalak

3

es so arbeitete in Java Api (Java 8)

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

sampleListName ist eine Liste

Verwandte Themen