如何将sqlite json列转换为Spark字符串或结构?

时间:2019-04-07 14:23:50

标签: java python sqlite jdbc pyspark

我有一个sqlite数据库,其中的列另存为json,有些只是数组,有些是对象数组 数据不是太大,一个表中大约有100万行,而另一个表中又有600万行。现在,我想提高查询速度并将这些数据提取到索引化且更易于管理的

问题是,spark将json列视为BigDecimal,但我不知道为什么或如何解决,发现了一些东西,但没有任何帮助。

Caused by: java.sql.SQLException: Bad value for type BigDecimal : [56641575300, 56640640900, 56640564100, 56640349700, 18635841800, 54913035400, 6505719940, 56641287800, 7102147726, 57202227222, 57191928343, 18633330200, 57193578904, 7409778074, 7409730079, 55740247200, 56641355300, 18635857700, 57191972388, 54912606500, 6601960745, 57191972907, 56641923500, 56640256300, 54911965100, 45661930800, 55474245300, 7409541556, 7409694518, 56641363000, 56519446200, 6504106170, 57191975866, 56640736700, 55463741500, 56640319300, 56640861000, 54911965000, 56561401800, 6504731849, 24342836300, 7402491855, 22950414800, 6507741522, 6504199636, 7102381436, 57191895642, 18634536800, 57196623329, 7005988322, 56013334500, 18634278500, 57191983462, 7409545828, 57204194408, 56641031400, 56641436400, 6504659572, 36829162100, 24766932600, 8256434300]
    at org.sqlite.jdbc3.JDBC3ResultSet.getBigDecimal(JDBC3ResultSet.java:196)

我尝试的是加载sqlite驱动程序,然后使用SQLContext

打开数据库
df = sqlContext.read.format('jdbc').options(url='jdbc:sqlite:../cache/iconic.db', dbtable='coauthors', driver='org.sqlite.JDBC').load()

在spark抱怨列类型后,我尝试将其转换为字符串,以便可以将其进一步解析为json

schema = ArrayType(IntegerType())
df.withColumn('co_list', from_json(df['co_list'].cast(StringType()), schema))

但这会引发相同的错误,因为它没有更改任何内容

我也尝试从一开始就设置表架构,但似乎pyspark不允许我这样做

df = sqlContext.read.schema([...]).format('jdbc')...
# Throws
pyspark.sql.utils.AnalysisException: 'jdbc does not allow user-specified schemas.;'

行看起来像这样

# First table
1   "[{""surname"": ...}]"  "[[{""frequency"": ""58123"", ...}]]"   74072   14586   null    null    null    "{""affiliation-url"":}"    "[""SOCI""]"    null    0   0   1

# Second table
505 "[{""surname"": ""Blondel"" ...}, {""surname"": ""B\u0153ge"" ..}, ...]"    "1999-12-01"    21  null    null    null    0

希望有办法。

1 个答案:

答案 0 :(得分:0)

找到解决方案后,应使用jdbc阅读器加载数据库,并且要自定义列的转换,应将属性传递给驱动程序

这是解决方案

connectionProperties = { 
    "customSchema": 'id INT, co_list STRING, last_page INT, saved INT',
    "driver": 'org.sqlite.JDBC'
}

df = sqlContext.read.jdbc(url='jdbc:sqlite:../cache/iconic.db', table='coauthors', properties=connectionProperties)

这样,您可以控制spark如何在内部映射数据库表的列。