web-dev-qa-db-fra.com

Comment utiliser Column.isin avec liste?

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

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

Le code ci-dessus lève l'exception suivante.

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)

Ci-dessous ma tentative de le réparer. Il compile et s'exécute mais ne renvoie aucune correspondance. Pas certain de pourquoi.

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

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

Selon la documentation, isin prend un vararg, pas une liste. La liste est en fait un nom déroutant ici. Vous pouvez essayer de convertir votre liste en vararg comme ceci:

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

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

Votre variante avec mkString est compilée, car une seule chaîne est également une variable (avec un nombre d'arguments égal à 1), mais ce n'est pas ce que vous voulez réaliser.

104
Niemand

Cela a fonctionné comme ceci dans Java Api (Java 8)

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

sampleListName est une liste

13
Anandkumar

Encore plus facile:

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

Sauf si vous avez beaucoup de valeurs de liste, ce n'est généralement pas le cas.

0
Pedro H