2017-03-01 2 views
0

J'ai trouvé un post similaire sur Stackoverflow. Cependant, je n'ai pas pu résoudre mon problème. C'est pourquoi j'écris ce post.spark scala typesafe config sécurisé itérer sur la valeur d'un nom de colonne spécifique

Aim

Le but est d'effectuer une projection sur colonne [= projection des colonnes de filtres] pendant le chargement d'une table SQL (I utilise SQL Server).

Selon le livre de cuisine scala c'est le moyen de filtrer colums [en utilisant un tableau]:

sqlContext.read.jdbc(url,"person",Array("gender='M'"),prop) 

Cependant, je ne veux pas hardcode Array ("col1", "col2", ...) dans mon code Scala c'est pourquoi j'utilise un fichier de configuration avec typesafe (voir ci-dessous).

fichier Config

dataset { 
    type = sql 
    sql{ 
     url = "jdbc://host:port:user:name:password" 
     tablename = "ClientShampooBusinesLimited" 
     driver = "driver" 
     other = "i have a lot of other single string elements in the config file..." 
     columnList = [ 
     { 
      colname = "id" 
      colAlias = "identifient" 
     } 
     { 
      colname = "name" 
      colAlias = "nom client" 
     } 
     { 
      colname = "age" 
      colAlias = "âge client" 
     } 
     ] 
    } 
} 

LET de mise au point sur de 'COLUMNLIST': Le nom de la colonne SQL correspondent à exatecly 'colname'. 'colAlias' est un champ que j'utiliserai plus tard.

fichier data.scala

lazy val columnList = configFromFile.getList("dataset.sql.columnList") 
lazy val dbUrl = configFromFile.getList("dataset.sql.url") 
lazy val DbTableName= configFromFile.getList("dataset.sql.tablename") 
lazy val DriverName= configFromFile.getList("dataset.sql.driver") 

configFromFile est créé par moi-même dans une autre classe personnalisée. Mais cela n'a pas d'importance. Le type de columnList est "ConfigList" ce type vient de typesafe.

fichier principal

def loadDataSQL(): DataFrame = { 

val url = datasetConfig.dbUrl 
val dbTablename = datasetConfig.DbTableName 
val dbDriver = datasetConfig.DriverName 
val columns = // I need help to solve this 


/* EDIT 2 march 2017 
    This code should not be used. Have a look at the accepted answer. 
*/ 
sparkSession.read.format("jdbc").options(
    Map("url" -> url, 
    "dbtable" -> dbTablename, 
    "predicates" -> columns, 
    "driver" -> dbDriver)) 
    .load() 
} 

Donc mon problème est d'extraire les valeurs 'colnames afin de les mettre dans un tableau approprié. Quelqu'un peut-il m'aider à écrire la bonne opération de «val colonnes»?

Merci

Répondre

1

Si vous cherchez un moyen de lire la liste des valeurs colname dans un tableau Scala - je pense que cela le fait:

import scala.collection.JavaConverters._ 

val columnList = configFromFile.getConfigList("dataset.sql.columnList") 
val colNames: Array[String] = columnList.asScala.map(_.getString("colname")).toArray 

Avec le fichier fourni cela entraînerait Array(id, name, age)

EDIT: pour ce qui est votre objectif réel, je ne sais pas en fait d'une option nommée predication (et je ne puis trouver des preuves pour l'un dans les sources, en utilisant Spark 2.0.2).

JDBC Data Source effectue un "pushdown de projection" basé sur les colonnes réelles sélectionnées dans la requête utilisée. En d'autres termes - que sélectionnés colonnes seraient lues à partir de DB, de sorte que vous pouvez utiliser le tableau colNames dans un select immédiatement après la création DF, par exemple:

import org.apache.spark.sql.functions._ 

sparkSession.read 
    .format("jdbc") 
    .options(Map("url" -> url, "dbtable" -> dbTablename, "driver" -> dbDriver)) 
    .load() 
    .select(colNames.map(col): _*) // selecting only desired columns 
+0

Cher Tzach Zohar, c'est pétantes ce que je recherchais pour. Merci beaucoup pour votre aide. – S12000

+0

Cependant, j'obtiens une erreur dans les colonnes "predication" ->, il dit "surchargé". Savez-vous quel est le problème?Merci – S12000

+0

Pas sûr de l'erreur que vous référez, mais j'ai mis à jour ma réponse en espérant vous aider avec votre objectif réel de lire seulement les colonnes sélectionnées de DB –