ES更新嵌套数组(使用Java API)
最近在做一個(gè)需求,一開(kāi)始的時(shí)候以為用es腳本能搞定,耽擱了一天半時(shí)間。
后來(lái)用了Java client 的api來(lái)做,效率快多了。
package com.XXX.XXXX.XXX;import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.assertj.core.util.Arrays; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptType; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map;@Slf4j @RunWith(SpringRunner.class) @SpringBootTest public class HestiaApplicationTests {@Resourceprotected RestHighLevelClient client;@Testpublic void contextLoads() {}/*** *先檢索、再更新文檔**/@Testpublic void search() throws IOException {try {SearchRequest searchRequest = new SearchRequest("zm_prod");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 第幾頁(yè)searchSourceBuilder.from(0);Map<String, Object> params = new HashMap<>();//課程標(biāo)簽:1.大班課;2.小班課;3.AI課;4.磨課 // Script script = new Script(ScriptType.INLINE, "painless", "ctx._source.values.base_info.course_mark == 2", params); // searchSourceBuilder.query(QueryBuilders.scriptQuery(script)); // searchSourceBuilder.query(QueryBuilders.matchQuery("_source.values.base_info.course_mark",2));searchSourceBuilder.query(QueryBuilders.termQuery("_id", 55074)); // searchSourceBuilder.query(QueryBuilders.matchAllQuery());// 每頁(yè)多少條數(shù)據(jù)searchSourceBuilder.size(1000);// 設(shè)置超時(shí)時(shí)間為2ssearchSourceBuilder.timeout(new TimeValue(2000));// 設(shè)置request要搜索的索引和類型 // searchRequest.indices("zm_prod").types("news");// 設(shè)置SearchSourceBuilder查詢屬性searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = client.search(searchRequest);SearchHit[] searchHits = searchResponse.getHits().getHits();if (ArrayUtils.isEmpty(searchHits)) {log.info("searchHits = 666666666666666666666");}for (SearchHit hit : searchHits) {//文檔的主鍵String id = hit.getId();String index = hit.getIndex();String type = hit.getType();String sourceAsString = hit.getSourceAsString();if(!sourceAsString.contains("course_mark")){continue;}//源文檔內(nèi)容Map<String, Object> sourceAsMap = hit.getSource(); // String s = JSON.toJSONString(sourceAsMap);Map<String, Object> values = (Map)sourceAsMap.get("values");Map<String, Object> base_info = (Map)values.get("base_info");Integer course_mark = (Integer) base_info.get("course_mark");String base_infostr = JSON.toJSONString(base_info);if(null!=course_mark){if(course_mark==1||course_mark==2||course_mark==3){log.info(" base_infostr = " + base_infostr);//TODO 這個(gè)地方反向的在map里面添加字段,然后重新組裝,然后更新當(dāng)前的數(shù)據(jù)base_info.put("BBB",7777);values.put("base_info",base_info);UpdateRequest uRequest = new UpdateRequest().index(index).type(type).id(id).doc(XContentFactory.jsonBuilder().startObject().field("values", values).endObject());BulkRequest blkRequest = new BulkRequest();blkRequest.add(uRequest);// 執(zhí)行BulkResponse bulkResponse = client.bulk(blkRequest); // for (UpdateRequest uprequest : list) { // bulkResponse.add(uprequest); // }// BulkResponse bulkResponse = bulkResponse.execute().actionGet();if (bulkResponse.hasFailures()) {System.out.println("批量錯(cuò)誤!");}}}}} catch (IOException e) {e.printStackTrace();log.error(ExceptionUtils.getMessage(e));}}}-------------------------------------------------------------------------------------------------------------------
以下是參考別的博主的內(nèi)容;
最近在學(xué)習(xí)ElasticSearch,前些天在工作中遇到一個(gè)難以解決的問(wèn)題,問(wèn)題正如標(biāo)題所示在使用Java TransportClient更新ES復(fù)雜數(shù)據(jù)結(jié)構(gòu)數(shù)組,最后請(qǐng)教大佬問(wèn)題得以解決。此文章將詳細(xì)描述問(wèn)題并提供解決辦法。
博主要更新的數(shù)據(jù)格式大致如下:?
原數(shù)據(jù):一個(gè)嵌套類型的數(shù)組
更新后的數(shù)據(jù):將商場(chǎng)01對(duì)應(yīng)的數(shù)據(jù)從數(shù)組刪除
博主是ES小白,對(duì)于此類型的數(shù)據(jù)不知道如何正確使用?UpdateRequest進(jìn)行更新。
于是乎使用如下方法,value表示更新的數(shù)據(jù)(也就是沒(méi)有"商場(chǎng)01"的list數(shù)據(jù)),對(duì)于value的類型博主嘗試過(guò)Object和List<>,甚至將list轉(zhuǎn)成Json格式結(jié)果都不可以。
// XXXXXXXXX表示要更新的數(shù)據(jù)
// List value = XXXXXXXXX;
// XXXXXXXXX表示要更新的數(shù)據(jù)
// Object value = XXXXXXXXX;
List> value = XXXXXXXXX; // 這個(gè)好用
updateRequest.doc(XContentFactory.jsonBuilder()
? ? ? ? ? ? ? ? ? ? .startObject()
? ? ? ? ? ? ? ? ? ? .field("name", value)
? ? ? ? ? ? ? ? ? ? .field(flag, 1)
? ? ? ? ? ? ? ? ? ? .endObject()); ? ?
最后大佬告訴我要將List value轉(zhuǎn)成List> value,也就是當(dāng)使用updateRequest的時(shí)候,對(duì)于字段類型是對(duì)象數(shù)組的,ES是無(wú)法正常更新的,要將List中的泛型專程Map類型,Es才會(huì)識(shí)別。
?// 將嵌套數(shù)組對(duì)象轉(zhuǎn)Set格式(List也可以),否則無(wú)法進(jìn)行更新(會(huì)報(bào)錯(cuò))
? ? ? ? List> set = Lists.newArrayList();
? ? ? ? Map map = Maps.newHashMap();
? ? ? ? Class clazz;
? ? ? ? // 使用反射動(dòng)態(tài)將Set中的屬性值放入Map中
? ? ? ? for (Object obj : setArry) {
? ? ? ? ? ? clazz = obj.getClass();
? ? ? ? ? ? // 遍歷當(dāng)前對(duì)象的屬性值
? ? ? ? ? ? for (Field field : clazz.getDeclaredFields()) {
? ? ? ? ? ? ? ? field.setAccessible(true);
? ? ? ? ? ? ? ? String name = field.getName();
? ? ? ? ? ? ? ? Object value = field.get(obj);
? ? ? ? ? ? ? ? map.put(name, value);
? ? ? ? ? ? }
? ? ? ? ? ? set.add(map);
? ? ? ? ? ? map = Maps.newHashMap();
由于此種數(shù)組類型較多,博主使用反射,可以兼容每種數(shù)組類型。最后成功更新數(shù)據(jù)。
---------------------------------------------------------------------------------------------------------------
同時(shí)參考了
如果更新一條文檔,而且知道文檔id的前提下可以使用UpdateRequest即可實(shí)現(xiàn),代碼如下:
/*** 根據(jù)文檔id更新* @throws IOException*/@Testpublic void test() throws IOException {UpdateRequest request = new UpdateRequest("sub_bank1031","sub_bank","SvjgP24BndtcmnpzbiuL");request.doc("{\"aliasName\":\"中國(guó)農(nóng)業(yè)發(fā)展銀行林州市支行444\",\"bankType\":\"ADB\",\"bankTypeName\":\"中國(guó)農(nóng)業(yè)發(fā)展銀行\(zhòng)",\"cityId\":\"410500\",\"cityName\":\"安陽(yáng)市\(zhòng)",\"createTime\":1515719190000,\"createUser\":\"system\",\"id\":\"000238a326b044e9ae10cfe4298f4c44\",\"isEnabled\":\"1\",\"name\":\"中國(guó)農(nóng)業(yè)發(fā)展銀行林州市支行\(zhòng)",\"provinceId\":\"410000\",\"provinceName\":\"河南省\",\"unionNumber\":\"203496100010\"}", XContentType.JSON);UpdateResponse resp = highLevelClient.update(request, RequestOptions.DEFAULT);println(resp.getResult());}
但是如果不知道文檔id的情況如果還想使用UpdateRequest更新文檔就需要先使用SearchRequest根據(jù)某個(gè)條件查詢符合條件的文檔,然后再循環(huán)更新文檔即可。
上面操作略顯麻煩,需要多條http請(qǐng)求才能完成,要更新的文檔數(shù)量很多時(shí)將大大降低系統(tǒng)響應(yīng)速度,這時(shí)候我們可以使用es的UpdateByQueryRequest來(lái)實(shí)現(xiàn)該功能。
PS:
pom文件es相關(guān)依賴如下:
??<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>6.8.0</version></dependency><!-- elasticsearch high level --> ???<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><exclusions><exclusion><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId>????????????????</exclusion></exclusions><version>6.8.0</version></dependency>總結(jié)
以上是生活随笔為你收集整理的ES更新嵌套数组(使用Java API)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: springcloud实践之断路器:Hy
- 下一篇: 《深入理解Java虚拟机》读后总结(一)