1 dataframe写入es
'''
es_url: ip地址
es_port:端口
es_user:用户名
es_pass:密码
'''
spark=SparkSession.builder\
.config("spark.es.nodes",es_url)\
.config("spark.es.port",es_port)\
.config("es.net.http.auth.user",es_user)\
.config("es.net.http.auth.pass",es_pass)\
.config("es.mapping.id","id")\
.config("es.nodes.wan.only","true")\
.config("es.write.operation","upsert").getOrCreate()
'''
cancer_example:索引名(相当于库名)
_doc:类型(相当于表)
'''
# 读es
df=spark.read.format('org.elasticsearch.spark.sql').option('es.resource', 'cancer_example/_doc')
# 写es
df.write.format('org.elasticsearch.spark.sql').option('es.resource', 'cancer_example/_doc').mode("Append").save()
以上代码根据cancer_example索引的id进行更新,id若不存在就创建,若存在就更新
上面代码SparkSession里的一大堆配置可以在读或写es时再配置,以下是等价写法
spark=SparkSession.builder.getOrCreate()
# 读es
df=spark.read.format('org.elasticsearch.spark.sql')\
.option("spark.es.nodes",es_url)\
.option("spark.es.port",es_port)\
.option("es.net.http.auth.user",es_user)\
.option("es.net.http.auth.pass",es_pass)\
.option("es.mapping.id","id")\
.option("es.nodes.wan.only","true")\
.option("es.write.operation","upsert")\
.option('es.resource', 'cancer_example/_doc')
# 写es
df.write.format('org.elasticsearch.spark.sql')\
.option("spark.es.nodes",es_url)\
.option("spark.es.port",es_port)\
.option("es.net.http.auth.user",es_user)\
.option("es.net.http.auth.pass",es_pass)\
.option("es.mapping.id","id")\
.option("es.nodes.wan.only","true")\
.option("es.write.operation","upsert")\
.option('es.resource', 'cancer_example/_doc').mode("Append").save()
2 注意点
我觉得下面两个注意点都是es不够成熟的bug。
2.1 dataframe有重复列时报错fail to pass field[doc]
dataframe若有重复列会报错fail to pass field[doc],这个错报的我云里雾里,不知道问题出在哪里。尤其是如果列很多,很难发现这个问题。具体报错信息示例如下:
org.elasticsearch.hadoop.rest.EsHadoopInvalidRequest: org.elasticsearch.hadoop.rest.EsHadoopRemoteException: x_content_parse_exception:[1:744][UpdateRequest] fail to parse field[doc]
建议数据写入Es前先试写几行到hdfs上,这样直接就会报有重复列的错误
2.2 不支持decimal格式
建议转化为int或string