ElasticSearch嵌套模型基本操作

news/2024/7/7 5:52:59 标签: elasticsearch

上篇介绍了ES嵌套模型使用场景和优缺点,本篇接着介绍关于ES嵌套的索引一些基本的操作,包括插入,追加,更新,删除,查询单独放下一篇文章介绍。

首先来看下如何添加数据,上篇提到了我们项目中有三个实体类分别是User,Quest,Kp。其关系是一对多对多,User里面有个List<Quest>字段可以包含多个Quest对象而每一个Quest对象又包含一个List<Kp>字段可以包含多个Kp实体,每个实体类本身又可以拥有多个自己的属性字段。

在这里其实也能感受到用动态索引模板的好处,就是我不要关注到底有多少个字段,我的实体类里面随时可以新增一个字段或多个字段进行索引,当然前提是你把动态模板的schema给定义好,这过程中也遇到一些问题,后面会在相关的文章中介绍。

现在我想添加"一条数据"进入索引,注意这里的一条数据,指的是向一次发送一次索引,因为嵌套索引它的嵌套文档每一个都是独立的document,所以看起来你向es索引了一条数据到其服务端后,doc的数量会大于1,这个其实很正常,下面解释一下。

现在我想索引一条User数据,但是User下面又包含了5个Quest实体,而每个Quest实体又包含了2个Kp知识点,那么最终到es里面显示的文档数量=1+5*2=11条数据,所以看起来你发送的一条数据,其实es服务端会把其拆分成独立的document,但是es会在内部标记他们的关系,在进行检索时可根据需要返回所有数据或者指定想要返回的数据。

(1)下面看下,如何添加一条数据的核心代码:

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就可以成功插入

(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),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。

输入图片说明



http://www.niftyadmin.cn/n/788183.html

相关文章

数据可视化~matplotlib显示二维图像

原文链接&#xff1a;http://www.juzicode.com/archives/2514 matplotlib中显示二维图像不再使用plot()方法&#xff0c;而是有专用的api接口imshow()&#xff0c;接受二维数组和特定形状的三维数组&#xff0c;如果是三维数组第三维是3或者4&#xff0c;3正好对应rdb三通道彩…

Flutter移动应用开发实战——注释

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。

TTTTTTTTTTTTT LA 2191 树状数组 稍修改

题意&#xff1a;给出n个数字&#xff0c;操作有修改&#xff08;S&#xff09;和输出区间和(M)。 #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queu…

pyautogui: 有了Python键盘鼠标都可以省着用了

原文链接&#xff1a;http://www.juzicode.com/archives/3560 pyautogui可以用来控制键盘鼠标模拟人为操作&#xff0c;从而实现某些需要人工操作才能控制的场景&#xff0c;比如某些应用软件的测试、不适合爬虫的网页内容获取等场景。还可以用来截取屏幕&#xff0c;它附带了…

Flutter移动应用开发实战——第二章Flutter框架组件模块应用章节介绍配置安装

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。

数据分析~numpy数组变形记

原文链接&#xff1a;http://www.juzicode.com/archives/2923 numpy数组的变形可以实现对原始数组的维度改变、轴长度改变&#xff0c;假设原始数据的形状为(n1,n2….nx)&#xff0c;变化后的形状为(m1,m2,…my)&#xff0c;则要求 n1*n2….*nx m1*m2…*my。 1、a.resize(m,n…

MySQL 数据库 高级查询

1、连接查询select * from Info,Nation #笛卡尔积select * from Info,Nation where Info.NationNation.Code join on 连接select * from Info join Nation #join连接select * from Info join Nation on Info.NationNation.Code 2、联合查询select Code,Name from Infounionsele…

Flutter移动应用开发实战——布局机制步骤

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。