日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一起来学ES —— 浅谈Nested结构

發布時間:2023/12/3 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一起来学ES —— 浅谈Nested结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Nested是什么?

  • 直觀的說,Nested實際上就是Object的數組。如下,這個user就是個nested結構 { "user" : [ {"first" : "John","last" : "Smith"},{"first" : "Alice","last" : "White"} ] }

Nested 和 Object 是什么關系?

  • ES原生支持Object類型,也就是任意字段都可以是個對象,而ES又是所有字段都是多值,也就是都可以是list。那么在ES中Nested和Object List又是什么關系呢?
  • 這就要從Object說起了。Object雖然是個對象,但是實際存儲時是在當前文檔里打平存儲的。如上那個例子,如果只有一個user,那么在真實索引中實際上是下面這樣的
{"user.first" : "John","user.last" : "Smith" }
  • 而如果是個list,那么就成了
{"user.first" : ["John","Alice"],"user.last" : ["Smith","White"] }
  • 因為建索引時打平,因此檢索時ES就無法知道到底是John Smith還是John White了。因此引入了Nested結構。
  • Nested將list里的每個doc單獨變成子文檔進行存儲,因此在查詢時就可以知道具體的結構信息了。

Nested 查詢要注意什么?

  • Nested因為是單獨的子文檔存儲,因此在使用時,直接用?a.b.c?是無法訪問的,需要將其套在nested查詢里。除此之外,和其他的查詢并無差異。
{"query": {"nested": {"path": "user","query": {"match": {"user.first" : "John"}},"inner_hits": {}}} }
  • 如上所示,用一個nested套住真實query即可。默認的hit是返回父文檔,也就是大的doc。如果加上inner_hits會在父文檔的source中多一個inner_hits的字段,返回真實命中的object,其中有個offset表明list數組下標。
  • 需要注意的是,由于單獨存儲很耗資源,因此默認一個index最多只有50個nested字段。此外,雖然nested是單獨存儲的,但是其字段數也算入index總字段數,默認最多1000個。

Nested Aggregation是什么?

  • 對于Nested結構,有一點需要謹記的,就是他是個List結構。Nested Agg就是對這個list做agg操作,agg寫法和普通的一樣,只需要在外面套上nested即可。
  • 如官方文檔的例子,就是一個商品有許多賣家,對這些賣家的報價求最小值。

能否用Nested做動態kv?

  • Nested除了存儲固定的Object List,還有一種常用的場景就是用來存儲動態的KV。雖然ES天然支持dynamic mapping,但是其key都是固化在每一個doc中的,如果存儲用戶自定義報表數據。每個用戶的key差異很大,放在同一張表會出現大量空值。這是很浪費系統資源的行為,并且隨著Key的不斷增多,最終會超出index的最大key數量。
  • 因此用nested結構來處理這種動態kv就比較合適。 nested的本質就是將?{"tags":{"k1":"v1","k2":"v2"}}=>{"tags":[{"key":"key1","value":"v1"},{"key":"key2","value":"v2"}]}
  • 這樣一來就可以輕松處理動態kv。并且查詢依舊簡單,例如k1:v1 AND k2:v2變為
{"query": {"bool": {"must": [{"nested": {"path": "tags","query": {"query_string": {"query": "tags.key:k1 AND tags.value:v1"}}}},{"nested": {"path": "tags","query": {"query_string": {"query": "tags.key:k2 AND tags.value:v2"}}}}]}} }

動態kv如何做agg呢?

  • 普通查詢的確很簡單,但是agg就并不簡單了。原來的模式可以直接用真實字段tags.k1做agg,但是在nested里k1已經變成了一個字段的值,因此沒法直接做agg了。
  • 這時就需要引入script大法了。其實agg的本質就是從每個doc的正排里取一個值,用這個值做聚合。因此我們只需要用script遍歷list,找到對應的key然后返回其value即可。
  • 簡單寫了個如下所示,如果有更好的方法歡迎留言。
  • 注意!!! 由于nested單獨存儲,因此doc里并沒有nested數據,需要用params從source中拿。性能很差,僅可用于少量數據場景!
{ ..."aggs": {"test_agg": {"terms": {"script": {"inline": "for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']=='k1'){return params['_source']['tags'][i]['value']}}","lang": "painless"},"size": 5}}} }
  • 在使用中我們還可以把script存在來,來加速運算,減少緩存。(注意:5.6以后將code改為了source字段,具體寫法參閱文檔)
POST _scripts/is_tag_key {"script":{"lang": "painless","code":"for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']==params.key){return params['_source']['tags'][i]['value']}}"} }
  • 這樣用起來就簡單多了
{ ..."aggs": {"test_agg": {"terms": {"script": {"stored": "is_tag_key","params": {"key": "k1"}},"size": 5}}} }

怎么在kibana里做agg呢?

  • kibana其實和上面的一樣,也是用script.不過只支持inline的,在script field配置。不過注意一定不能太多,因為每一個inline script都是一個單獨的script都需要消耗存儲資源。

參考資料

  • nested datatype
  • nested query
  • nested agg
  • How to use scripts
  • painless DEBUG

版權聲明

  • 自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)
  • 本文首發于:?http://czjxy881.coding.me/

總結

以上是生活随笔為你收集整理的一起来学ES —— 浅谈Nested结构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。