// 写elasticsearch的代码
ds.write
.format("org.elasticsearch.spark.sql")
.option("es.nodes.wan.only", "true")
.option("es.mapping.id", "_id")
.option("es.mapping.exclude", "_id")
.option("es.nodes", host)
.option("es.port", port)
.option("es.update.script.lang","painless")
.option("es.update.script.inline",script) // es.update.script.inline 6.0以及之后的版本
.option("es.update.script.params", params)
.option("es.write.operation", "upsert")
.option("es.batch.write.retry.count", 3)
.option("es.update.retry.on.conflict", 3)
.option("es.mapping.exclude", "_id")
.mode("append")
.save(index_name)
// 读取elasticsearch的代码配置
val ds = spark.read
.format("org.elasticsearch.spark.sql")
.option("es.read.metadata", "true") // 读取元数据信息
.option("es.read.metadata.field", "_metadata")
.option("es.nodes.wan.only","true") // 公网的时候必传
.option("pushdown", "true")
.option("es.port",port)
.option("es.net.ssl","false")
.option("es.nodes", host)
.option("query", query) // 传入查询的dsl语句
.option("es.read.field.include", includeField) // 读取数据的时候可以在这个进行字段筛选
.option("es.read.field.as.array.include", arrIncludeField) // 在读取数组的时候需要加这个参数,否则无法识别
.option("es.mapping.date.rich", "false")
.load(index_name)
1、es.nodes.wan.only
如果运行的spark程序和你的elasitcsearch是在同一个网段的时候,不加这个是没有问题的。但是如果不在同一个网段比如是在公网上面的话,则会报请求失败的错误。
2、es.update.retry.on.conflict
如果是并发更新的时候,如果是更新到同一条记录上的时候则会报冲突,所以要设置这个参数
3、es.update.script.inline
elasticsear的spark插件在6.0版本之前是es.update.script这个参数,由于我自己用的是5.x的版本所以用的是es.update.script参数,但是这里在更新嵌套类型的数据结构的时候会报无法转成scala.tuple2的错误,只需要使用es.update.script.inline这个参数就能解决,但是使用这个参数在更新es7.0的时候还是会报这个错误:https://discuss.elastic.co/t/upsert-nested-fields-with-spark/128813
附上spark on elasticsearch的配置项链接:https://www.elastic.co/guide/en/elasticsearch/hadoop/current/configuration.html
4、spark-sql的udf里面获取广播变量的问题
今天碰到一个类似于:https://segmentfault.com/q/1010000008010132这个的问题,在udf里面调用广播变量的value获取值一直报空指针,后来在udf的类里面 将广播变量作为成员变量获取到了。由于udf的函数的类文件会分发到各个excutor节点上进行调用所以构造好的广播变量的成员变量在各个executor上也能顺利获取到。