使用Elasticsearch with Spark时,更新现有实体的正确方法是什么?
我想要以下内容:
但是,有几个问题:
如果为了测试,我在新值的映射中对现有的_id
进行硬编码,则抛出以下异常:
org.elasticsearch.hadoop.rest.EsHadoopInvalidRequest
如何检索_id
,以及如何将其传递回Spark?
我在下面添加了以下代码,以便更好地说明我的目标:
JavaRDD<Map<String, Object>> esRDD = JavaEsSpark.esRDD(jsc, INDEX_NAME+"/"+TYPE_NAME,
"?source=,field1,field2).values();
Iterator<Map<String, Object>> iter = esRDD.toLocalIterator();
List<Map<String, Object>> listToPersist = new ArrayList<Map<String, Object>>();
while(iter.hasNext()){
Map<String, Object> map = iter.next();
// Get existing values, and do transformation logic
Map<String, Object> newMap = new HashMap<String, Object>();
newMap.put("_id", ??????);
newMap.put("field1", new_value);
listToPersist.add(newMap);
}
JavaRDD javaRDD = jsc.parallelize(ImmutableList.copyOf(listToPersist));
JavaEsSpark.saveToEs(javaRDD, INDEX_NAME+"/"+TYPE_NAME);
理想情况下,我希望更新现有地图,而不是创建新地图。
在使用Spark时,是否有任何示例代码可以显示更新elasticsearch中现有实体的正确方法?
谢谢
答案 0 :(得分:0)
尝试将此upsert添加到Spark:
.config("es.write.operation", "upsert")
将允许您向现有文档添加新字段
答案 1 :(得分:0)
根据Elasticsearch Configuration,您可以通过将读取元数据选项设置为true来获得_id之类的文档元数据:
.config("es.read.metadata", "true")
我认为您不能使用'_id'作为字段名称。
但是您可以使用其他名称创建新字段,例如:
newMap.put("idfield", yourId);
然后将新字段的名称设置为“映射ID”选项的值,以通知Elastic该字段具有文档ID:
.config("es.mapping.id", "idfield")
顺便说一句,不要忘记将写入操作设置为更新:
.config("es.write.operation", "update")
答案 2 :(得分:0)
这就是我的操作方式(Scala / Spark 2.3 / Elastic-Hadoop v6.5)。
要读取(id或其他元数据):
Graphics
要更新ES中的特定列:
spark
.read
.format("org.elasticsearch.spark.sql")
.option("es.read.metadata",true) // allow to read metadata
.load("yourindex/yourtype")
.select(col("_metadata._id").as("myId"),...)