上篇介绍了ES嵌套模型使用场景和优缺点,本篇接着介绍关于ES嵌套的索引一些基本的操做,包括插入,追加,更新,删除,查询单独放下一篇文章介绍。java
首先来看下如何添加数据,上篇提到了咱们项目中有三个实体类分别是User,Quest,Kp。其关系是一对多对多,User里面有个List<Quest>字段能够包含多个Quest对象而每个Quest对象又包含一个List<Kp>字段能够包含多个Kp实体,每一个实体类自己又能够拥有多个本身的属性字段。json
在这里其实也能感觉到用动态索引模板的好处,就是我不要关注到底有多少个字段,个人实体类里面随时能够新增一个字段或多个字段进行索引,固然前提是你把动态模板的schema给定义好,这过程当中也遇到一些问题,后面会在相关的文章中介绍。微信
如今我想添加"一条数据"进入索引,注意这里的一条数据,指的是向一次发送一次索引,由于嵌套索引它的嵌套文档每个都是独立的document,因此看起来你向es索引了一条数据到其服务端后,doc的数量会大于1,这个其实很正常,下面解释一下。app
如今我想索引一条User数据,可是User下面又包含了5个Quest实体,而每一个Quest实体又包含了2个Kp知识点,那么最终到es里面显示的文档数量=1+5*2=11条数据,因此看起来你发送的一条数据,其实es服务端会把其拆分红独立的document,可是es会在内部标记他们的关系,在进行检索时可根据须要返回全部数据或者指定想要返回的数据。框架
(1)下面看下,如何添加一条数据的核心代码:ui
Kp k1=new Kp() Kp k2=new Kp() List<Kp> kps=new ArrayList<Kp>() kps.add(kp1) kps.add(kp2) //========================== Quest quest=new Quest() quest.setKps(kps) List<Quest> quests=new ArrayList<Quest>() quests.add(quest) //========================== User user=new User() user.setUid("001") user.setQuests(quests) //组装好Java Bean后,转成json向es服务端进行索引 String json=JSON.toJSON(user).toString();//这里用的FastJson框架 IndexResponse response=client.prepareIndex("Index", "type",user.getUid()).setSource(json).execute().actionGet();
能够发现插入的方法仍是比较简单清晰的,就是将一个Java Bean转成json后进行索引,只要服务端有配置描述其schemal就能够成功插入code
(2)在第二层嵌套数据里面添加一条新的数据到quests中对象
注意append操做,须要用到script来完成。索引
_ StringBuffer sb_json = new StringBuffer("ctx._source.quests += quest");//脚本主体 HashMap<String, Object> params = new java.util.HashMap<String, Object>()//Map组装 params.put("quest", JSON.toJSON(user.getQuests))//此处不能用JSON.toJSON(user.getQuests).toString方法,quest必须是一个对象,不然会报错 Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params)//组装脚本 client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get() //发送请求
上面的代码,是向已经存在某个User给它新增了一个Quest对象,注意这个Quest对象里面,若是有Kp的数据,依旧也能够添加进来。图片
(3)在第二层嵌套数据里面删除一条quests数据
- StringBuffer sb_json = new Stri ngBuffer("ctx._source.quests.removeAll{it.qid == remove_id}"); java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); params.put("remove_id", "qid2");//此处不能用JSON.toJSON(user.getQuests).toString方法,quest必须是一个对象,不然会报错 Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params); client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get();
(4)在第三层嵌套数据里面添加一条Kp数据
StringBuffer sb_json = new StringBuffer("ctx._source.quests.findAll { if(it.qid==qid2||it.qid==qid3) { it.kps += kp5 } } "); java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); params.put("qid2", "qid2"); params.put("qid3", "qid3"); params.put("kp5",JSON.toJSON(kp1)); Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params); client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get();
(5)在第三层嵌套数据里面删除一条Kp数据
- StringBuffer sb_json = new StringBuffer("ctx._source.quests.findAll { if(it.qid==qid2||it.qid==qid3) { it.kps.removeAll {it.kid==kid} } } "); //删除第三层数据 java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); params.put("qid2", "qid2"); params.put("qid3", "qid3"); params.put("kid", "kid3"); Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params); client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get();
(6)更新第三层嵌套里面的数据
A:若是是字段数比较多,大范围更新,建议直接删除后添加
B: 若是字段数比较少,小范围更新,就使用下面的局部更新的API便可
- StringBuffer sb_json = new StringBuffer("ctx._source.quests.findAll { if(it.qid==qid3) { it.kps.findAll{ if(it.kid==kid){ it.kname=kname;it.kmd=kmd } } } } "); //更新第三层数据 java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); params.put("qid2", "qid2"); params.put("kname","地球的引力"); params.put("kid","kid5"); params.put("kmd",0.78); Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params); client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get();
(7)同理更新第二层嵌套里面的数据
- StringBuffer sb_json = new StringBuffer("ctx._source.quests.findAll { if(it.qid==qid) { it.qtime=qtime } } "); //更新第三层数据 java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>(); params.put("qid", "qid1");//此处不能用JSON.toJSON(user.getQuests).toString方法,quest必须是一个对象,不然会报错 params.put("qtime",5558) Script script = new Script(sb_json.toString(), ScriptService.ScriptType.INLINE, "groovy", params); client.prepareUpdate(dynamicIndexName, typeName, uid).setScript(script).execute().get();
总结:
本篇介绍了ES嵌套索引的添加,修改,删除的操做,咱们不难发现都是用script脚原本完成的,ES默认用的是Groovy若是想更加深刻的了解script脚本的各类语法,建议直接熟悉下Groovy的语法。虽然理论上咱们经过script脚原本完成对无限嵌套索引的操做,但实际应用开发中,须要注意几点:
(1)不要出现太多层的嵌套结构,建议不要超过3级
(2)每层的嵌套结构List里面,不建议存储太多的数据,若是存的太多,删除,更新操做的时间都会是线性的,由于es须要遍历整个List(最坏状况下)找到你须要删或者改的数据
有什么问题能够扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。