ElasticSearch嵌套模型基本操做

上篇介紹了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),在後臺留言諮詢。 技術債不能欠,健康債更不能欠, 求道之路,與君同行。

輸入圖片說明

相關文章
相關標籤/搜索