美文网首页程序员ElasticSearch
ElasticSearch 怎样更新list中的元素

ElasticSearch 怎样更新list中的元素

作者: 追杀丘比特 | 来源:发表于2018-03-06 09:20 被阅读0次
{
  "_index": "school",
  "_type": "student",
  "_id": "id_4",
  "_version": 1,
  "_score": 1,
  "_source": {
    "name": "this name is name",
    "id": 4,
    "tags": [
      "班长",
      "学习委员",
      "文艺委员"
    ]
  }
}

可以看到在以上数据中tags为list类型,假设在一个业务场景中,我们需要对这个list中的值进行更新(删除或者添加),按照常规的操作方式,我们可能需要先取出tags的所有值,然后利用elastic search的Partial更新来更新tags的值。其实相比较与这种更新方式,es提供的构建Script来实现这种操作可能更加符合业务需求,如下:

1.建立一个TransPortClient

public class OldTransportClient {
    private Logger logger = Logger.getLogger(OldTransportClient.class);

    private TransportClient client;
    private IndicesAdminClient adminClient;

    @Value("${es.host}")
    private String host;

    @PostConstruct
    @SuppressWarnings({ "unchecked", "resource" })
    public synchronized TransportClient setupTransportClient() throws UnknownHostException {
        if (client == null) {
            Settings settings = Settings.builder().put("cluster.name", "ceiec-test")
                    .put("client.transport.sniff", true).build();
            client = new PreBuiltTransportClient(settings)
                    .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(host), 9300));
            logger.info("====== transport client set up! =======");
        }
        return client;
    }

    public synchronized IndicesAdminClient setupAdminClient() {
        if (client != null) {
            if (adminClient == null) {
                adminClient = client.admin().indices();
                logger.info("===== admin client set up ======");
            }
        }else {
            logger.error("transport client is not set up,please set up it!");
        }
        return adminClient;
    }
}

2.新建一个Script

 /**
     * update item with array in elasticSearch
     * @param index
     * @param type
     * @param id
     * @param value
     * @param delete : (default false)
     *          -----> true  delete an element from array
     *          -----> false add an element to array
     * @throws Exception
     */
public void updateExistList(String index,String type,String id,String field,String value,boolean isDelete) throws Exception{
        client = oldclient.setupTransportClient();
        Map<String,Object> params = new HashMap<>();
        params.put(field,value);
        String script_str;
        if (isDelete){
           script_str = "if (ctx._source."+field+".indexOf(params."+field+") != -1){" +
                    "ctx._source."+field+".remove(ctx._source."+field+".indexOf(params."+field+"))}";
        }else {
          //表示如果该doc不包含该字段,在该doc新建字段并赋值value,
          //如果存在该字段,会比较传入的值是否存在于list中,如果不存在就添加
            script_str = "if(!ctx._source.containsKey('"+field+"')){ctx._source."+field+"=[params."+field+"]}else{" +
                    "if (ctx._source."+field+".indexOf(params."+field+") == -1){ ctx._source."+field+".add(params."+field+")}}";
        }
        Script script = new Script(ScriptType.INLINE,Script.DEFAULT_SCRIPT_LANG,script_str,params);
        logger.info("script:\n"+script);
        UpdateResponse updateResponse = client.prepareUpdate(index,type,id)
                .setScript(script)
                .get();
        System.out.println(updateResponse.status());
    }

通过以上操作,我们就可以对es中的list数据进行增加和删除.

以上是针对es的list存储的是简单类型比如String,number等类型进行的操作,那么假如list里面存储的是Object类型该怎么做呢,现在有如下的数据:

{
  "_index": "school",
  "_type": "student",
  "_id": "id_2",
  "_version": 9,
  "_score": 1,
  "_source": {
    "name": "this name is name",
    "id": 2,
    "tags": [
      "班长",
      "学习委员",
      "文艺委员"
    ],
    "permission": [
      {
        "user": "user1",
        "name": "zhangsan2"
      },
      {
        "user": "user2",
        "name": "zhangsan2"
      },
      {
        "user": "user3",
        "name": "zhangsan3"
      },
      {
        "user": "user3",
        "name": "zhangsan3"
      },
      {
        "user": "user4",
        "name": "zhangsan3"
      }
    ]
  }
}

我们可以看到permission字段是存储着Object的list,那我们想更新其中的元素该怎么操作呢?
其实方法很类似,我们只需要构建不同的script就可以实现啦,如下:

/**
* @param index
* @param type
* @param id
* @param field 需更新的字段
* @param value
* @param delete : (default false)
*          -----> true  delete an element from array
*          -----> false add an element to array
* @throws Exception
*/
public void updateExistListObject(String index,String type,String doc_id,Object o,String field,boolean isDelete) throws Exception{
        client = oldclient.setupTransportClient();
        Map<String,String> map = (Map<String, String>) o;
        String property = (String) map.keySet().toArray()[0];
        Map<String,Object> params = new HashMap<>();
        params.put(field,o);
        String script_str;
        if (isDelete){
           script_str = "for (int i=0;i<ctx._source."+field +".size();i++)" +
                    "{ if(ctx._source."+field+"[i]['"+property+"'] == params."+field+"."+property+")"+
                    "{ctx._source."+field+".remove(i)}}";
        }else {
          //表示如果该doc不包含该字段,在该doc新建字段并赋值value,
          //如果存在该字段,会比较传入的对象是否存在于list中存在的对象相等,如果不相等就添加,相等就更新
           script_str = "if(!ctx._source.containsKey('"+field+"'))" + "{ctx._source."+field+"=[params."+field+"]} " +
                    "else { for(int i=0; i<ctx._source."+ field +".size(); i++)"+
                    "{ if (ctx._source."+field+"[i]['"+property+ "'] != params."+ field+"."+property+")
                     {ctx._source."+field+".add(params."+field+");break;}}}";
        }
        Script script = new Script(ScriptType.INLINE,Script.DEFAULT_SCRIPT_LANG,script_str,params);
        logger.info("script:\n"+script);
        UpdateResponse updateResponse = client.prepareUpdate(index,type,doc_id)
                .setScript(script)
                .get();
        System.out.println(updateResponse.status());
    }

script可以实现相当复杂的功能,因此需要大家在实践中去构建符合自己业务逻辑的script。

相关文章

  • ElasticSearch 怎样更新list中的元素

    elastic search支持list类型的数据存储ElasticSearch中支持的数据类型假设我们有以下数据...

  • Java中对List集合的常用操作

    List中添加,获取,删除元素 List中是否包含某个元素 List中根据索引将元素数值替换 List中查看元素的...

  • Java中对List集合的常用操作

    list中添加,获取,删除元素;list中是否包含某个元素;list中根据索引将元素数值改变(替换);list中查...

  • python

    列表 List 语法 使用[],将list的元素括起来 使用a[] 来获取list中的元素,list[0]就是列表...

  • 2018-04-19 python中List添加、删除元素的几种

    源地址:python中List添加、删除元素的几种方法 一、python中List添加元素的几种方法 List 是...

  • List

    List是有序、可重复的容器有序:List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问...

  • 从屌丝到架构师的飞越(集合篇)-List

    一.介绍 List集合包括JavaList接口以及List接口的所有实现类.List集合中的元素允许重复,各元素的...

  • python使用

    一、list中的每个元素都进行小操作 list = list(map(小操作,list名字)) newList =...

  • 9.2-全栈Java笔记:List接口的特点和常用方法

    List特点和常用方法 List是有序、可重复的容器。 有序指的是:List中每个元素都有索引标记。可以根据元素的...

  • List中删除元素

    均属于笔记,仅供个人参考,有问题欢迎指正 1,使用普通的for循环删除,会因为指标前移(list的大小发生了变化,...

网友评论

    本文标题:ElasticSearch 怎样更新list中的元素

    本文链接:https://www.haomeiwen.com/subject/luclfftx.html