es的官方中文文檔
https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html
概念
es是基于Lucene,純java語(yǔ)言編寫(xiě)的分布式再芋,可擴(kuò)展,近實(shí)時(shí)性的高性能搜索引擎和數(shù)據(jù)分析引擎
es基礎(chǔ)構(gòu)成
-
doc
es中數(shù)據(jù)存儲(chǔ)的最小單元,對(duì)應(yīng)數(shù)據(jù)庫(kù)的一行數(shù)據(jù) -
Index
有具有相同字段的文檔列表組成,對(duì)應(yīng)數(shù)據(jù)庫(kù)的一個(gè)表,一個(gè)索引由一個(gè)或者多個(gè)分片組成 -
type
文檔類型挣棕,這個(gè)我們可以不用記辛孵,es后面的版本要把type去掉。之前的版本中洲守,索引和文檔中間還有個(gè)類型的概念,每個(gè)索引下可以建立多個(gè)類型沾凄,文檔存儲(chǔ)時(shí)需要指定index和type梗醇。從6.0.0開(kāi)始單個(gè)索引中只能有一個(gè)類型,7.0.0以后將將不建議使用搭独,8.0.0 以后完全不支持婴削。在7.0開(kāi)始,一個(gè)索引只能建一個(gè)Type為_(kāi)doc牙肝。 -
shards
分片唉俗。當(dāng)索引數(shù)據(jù)太大時(shí),受限于單個(gè)節(jié)點(diǎn)的磁盤(pán)配椭,內(nèi)存虫溜,處理能力等資源,需要將索引的數(shù)據(jù)水平拆分股缸,拆分后形成的每一個(gè)分片回落到不一樣的服務(wù)節(jié)點(diǎn)上衡楞,這樣顯著提升了es的性能,索引創(chuàng)建時(shí)需要指定分片敦姻,一旦分片被指定就無(wú)法更改 -
replicas
副本瘾境。是主分片的備份分片,副本主要是用于主分片的數(shù)據(jù)備份镰惦,同時(shí)也對(duì)外提供數(shù)據(jù)查詢服務(wù)迷守。副本分片提升了es的高可用性
分片shard和es集群的高可用高性能
分片的概念和kafka的分區(qū)很像,既有副本又各自擁有不同的數(shù)據(jù)并且分散在不同的節(jié)點(diǎn)旺入,index就是這些分片的topic兑凿。
一個(gè)索引中的數(shù)據(jù)保存通過(guò)hash取余決定保存在哪分片中凯力,相當(dāng)于水平分表也類似于kafka的分區(qū),分片有主分片和副本分片礼华,一個(gè)主分片可以設(shè)置多個(gè)副本分片咐鹤,在es集群中每個(gè)主分片存儲(chǔ)了es的部分?jǐn)?shù)據(jù),副本分片主要是用于備份主分片的數(shù)據(jù)圣絮,主分片分布在es的各個(gè)節(jié)點(diǎn)上祈惶,而各個(gè)主分片的副本分片也會(huì)分布到和主分片不同的節(jié)點(diǎn)上,當(dāng)集群中某個(gè)節(jié)點(diǎn)宕機(jī)時(shí)晨雳,分布在其他節(jié)點(diǎn)的副本分片就會(huì)頂替原來(lái)的主分片行瑞,這個(gè)體現(xiàn)了es的高可用性。
由于分片分散在各個(gè)不同的節(jié)點(diǎn)上餐禁,每個(gè)節(jié)點(diǎn)都有能力處理任意請(qǐng)求, 每個(gè)節(jié)點(diǎn)都知道集群中任一文檔位置突照,所以可以直接將請(qǐng)求轉(zhuǎn)發(fā)到需要的節(jié)點(diǎn)上帮非,所以其請(qǐng)求壓力和數(shù)據(jù)分析壓力也會(huì)分散到集群的各個(gè)節(jié)點(diǎn)上,實(shí)現(xiàn)了es的高性能讹蘑。我們最好通過(guò)輪詢的方式訪問(wèn)集群的節(jié)點(diǎn)
分片的原理就和數(shù)據(jù)庫(kù)的水平分表和kafka的分區(qū)是一個(gè)道理的末盔,既能保證高新南
下圖的流程展示es集群的高可用
圖一:es集群中有三個(gè)節(jié)點(diǎn),三個(gè)主分片座慰,三個(gè)副本分片陨舱,也就是每個(gè)分片擁有一個(gè)副本分片
圖二:主節(jié)點(diǎn)宕機(jī),node2通過(guò)選舉稱為新主節(jié)點(diǎn)
圖三:掛掉的node1的副本分片存儲(chǔ)在node3上,集群將副本分片P0調(diào)整為主分片版仔,這樣node1的數(shù)據(jù)就恢復(fù)回來(lái)了
圖四:es集群將為創(chuàng)建P0的副本分片游盲,和重新創(chuàng)建和node1一起掛掉的R1副本分片,并讓它們保存在和自己主分片不一樣的節(jié)點(diǎn)上蛮粮,也就是P0副本分片保存在node2上,R1副本分片保存在node3上益缎,下次就算是在宕機(jī),其中的一個(gè)節(jié)點(diǎn)存在有其他備份分片然想,保證了數(shù)據(jù)的不丟失莺奔,這就是es的高可用性
數(shù)據(jù)被存儲(chǔ)到哪個(gè)分片是由公式?jīng)Q定的:
shard = hash(routing) % number_of_primary_shards
routing 是一個(gè)可變值,默認(rèn)是文檔的 _id 变泄,也可以設(shè)置成一個(gè)自定義的值
分片的實(shí)時(shí)性和查詢性能
refresh
Elasticsearch 是基于 Apache Lucene 構(gòu)建的令哟,Lucene 是一個(gè)高性能的全文搜索引擎庫(kù)。在Lucene中妨蛹,索引是由多個(gè)段(segments)組成的屏富,每個(gè)段是一個(gè)獨(dú)立的倒排索引。
- 段(Segment):一個(gè)段是一個(gè)不可變的倒排索引滑燃,包含了一部分文檔的數(shù)據(jù)役听。段是Lucene索引的基本單位。
- 內(nèi)存緩沖區(qū)(Memory Buffer):新索引的文檔首先被寫(xiě)入內(nèi)存緩沖區(qū),實(shí)際是就是寫(xiě)入到j(luò)vm中典予。
- 索引寫(xiě)入器(Index Writer):負(fù)責(zé)將內(nèi)存緩沖區(qū)中的文檔寫(xiě)入新的段甜滨。
refresh 操作的主要目的是將內(nèi)存緩沖區(qū)中的文檔刷新到一個(gè)新的段中,使得這些文檔對(duì)搜索請(qǐng)求可見(jiàn)瘤袖。以下是refresh操作的具體流程
- 內(nèi)存緩沖區(qū):
新索引的文檔首先被寫(xiě)入內(nèi)存緩沖區(qū)(jvm),這個(gè)內(nèi)存緩沖區(qū)是位于jvm中 - 段創(chuàng)建:
當(dāng) refresh 操作被觸發(fā)時(shí)衣摩,內(nèi)存緩沖區(qū)中的文檔被寫(xiě)入一個(gè)新的段,此操作在jvm中進(jìn)行捂敌,所以段的創(chuàng)建也是在jvm中艾扮。
這個(gè)新的段是一個(gè)不可變的倒排索引,包含了內(nèi)存緩沖區(qū)中的文檔占婉。 - 段注冊(cè):
新創(chuàng)建的段被注冊(cè)到索引的搜索上下文中泡嘴。
注冊(cè)后,這些文檔對(duì)搜索請(qǐng)求可見(jiàn)逆济。 - 內(nèi)存緩沖區(qū)清空:
內(nèi)存緩沖區(qū)被清空酌予,準(zhǔn)備接收新的文檔。
當(dāng)我們向ES發(fā)送請(qǐng)求的時(shí)候奖慌,es貌似可以在我們發(fā)請(qǐng)求的同時(shí)進(jìn)行搜索抛虫。而這個(gè)實(shí)時(shí)建索引被搜索的過(guò)程實(shí)際上是一次es 索引提交(commit)的過(guò)程,如果這個(gè)提交的過(guò)程直接將數(shù)據(jù)寫(xiě)入磁盤(pán)(fsync)必然會(huì)影響性能简僧,所以es中設(shè)計(jì)了一種機(jī)制建椰,即:默認(rèn)情況下每隔一秒新寫(xiě)入的文檔在jvm中解析寫(xiě)到文件緩存系統(tǒng)之中形成段,這樣避免了比較損耗性能io操作岛马,此時(shí)Lucene才能搜索得到棉姐,數(shù)據(jù)才可以提供搜索。
es默認(rèn)每秒中執(zhí)行一次refresh
默認(rèn)情況下每個(gè)分片會(huì)每秒自動(dòng)刷新一次蛛枚。這就是為什么我們說(shuō) Elasticsearch 是 近 實(shí)時(shí)搜索: 文檔的變化并不是立即對(duì)搜索可見(jiàn)谅海,但會(huì)在一秒之內(nèi)變?yōu)榭梢?jiàn)可搜索。
flush
如果數(shù)據(jù)在文件系統(tǒng)緩存之中是很有可能在意外的故障中丟失蹦浦。這個(gè)時(shí)候就需要一種機(jī)制扭吁,可以將對(duì)es的操作記錄下來(lái),來(lái)確保當(dāng)出現(xiàn)故障的時(shí)候盲镶,保留在文件系統(tǒng)緩存的數(shù)據(jù)不會(huì)丟失侥袜,并在重啟的時(shí)候可以從這個(gè)記錄中將數(shù)據(jù)恢復(fù)過(guò)來(lái)。elasticsearch提供了translog來(lái)記錄這些操作溉贿。就是和數(shù)據(jù)庫(kù)wal思想很像(日志先行)
flush包括:將事務(wù)日志(translog)中的操作持久化到磁盤(pán)(fsync)和清空內(nèi)存中的緩沖區(qū)和事務(wù)日志兩個(gè)流程枫吧。
一個(gè)文檔被索引之后,就會(huì)被添加到內(nèi)存緩沖區(qū)宇色,并且追加到了translog
默認(rèn)每秒refresh一次九杂,refresh會(huì)清空內(nèi)存緩存颁湖,但是不會(huì)清空translog
refresh操作不斷發(fā)生,更多的文檔被添加到內(nèi)存緩沖區(qū)和追加到translog
translog周期性通過(guò)fsync進(jìn)行刷盤(pán)例隆,默認(rèn)5s甥捺,可通過(guò)參數(shù)index.translog.sync_interval、index.translog.durability控制镀层;并且每30分鐘或當(dāng)事務(wù)日志達(dá)到一定大辛獭(512MB)時(shí)自動(dòng)執(zhí)行一次 flush 操作。保證應(yīng)用重啟后先確認(rèn)最后記錄的commit point唱逢,commit point之后的變更操作通過(guò)落盤(pán)的translog進(jìn)行重構(gòu)恢復(fù)段
雖然translog主要保存在內(nèi)存中吴侦,但通過(guò)定期同步到磁盤(pán),確保了數(shù)據(jù)的持久性坞古,如果節(jié)點(diǎn)在兩次同步之間宕機(jī)备韧,內(nèi)存中的translog數(shù)據(jù)可能會(huì)丟失。但是绸贡,由于同步頻率較高(每5秒一次)盯蝴,這種數(shù)據(jù)丟失的風(fēng)險(xiǎn)非常小,如果es的數(shù)據(jù)非常重要听怕,可以通過(guò)index.translog.sync_interval配置縮短日志自動(dòng)的時(shí)間間隔,增加日志刷盤(pán)的頻率虑绵,但會(huì)影響性能尿瞭。如果es的數(shù)據(jù)不是那么重要,更es的性能翅睛,可減少日志刷盤(pán)的頻率
fsync
fsync:每個(gè)新段在文件系統(tǒng)緩存被持久化到磁盤(pán)的過(guò)程叫做fsync
有時(shí)候我們創(chuàng)建了一個(gè)文檔然后嘗試搜索它声搁,但卻沒(méi)有搜到。這個(gè)問(wèn)題的解決辦法是用 refresh API 執(zhí)行一次手動(dòng)刷新:
POST /_refresh //刷新所有的索引
POST /index_name/_refresh //只刷新(Refresh) 特定索引
es寫(xiě)性能優(yōu)化
降低刷新頻率(會(huì)影響實(shí)時(shí)性)
- 提高寫(xiě)性能捕发,我們可以啟動(dòng)多線程去進(jìn)行寫(xiě)操作
- 除了啟動(dòng)多線程外還可以通過(guò)調(diào)整刷新頻率來(lái)提升性能疏旨。
雖然刷新(refresh)是比提交輕量很多的操作,但它還是會(huì)有性能開(kāi)銷扎酷,并不是所有的情況都需要每秒刷新檐涝。如果你想優(yōu)化讀寫(xiě)速度而不是近實(shí)時(shí)搜索,可以通過(guò)設(shè)置refresh_interval法挨, 降低每個(gè)索引的刷新頻率:
PUT /my_logs
{
"settings": {
"refresh_interval": "30s" //每30秒刷新 my_logs 索引谁榜,默認(rèn)是每秒刷新
}
}
refresh_interval 是可以進(jìn)行動(dòng)態(tài)更新的,就是說(shuō)在生產(chǎn)環(huán)境中凡纳,當(dāng)你正在建立一個(gè)大的新索引時(shí)窃植,可以先關(guān)閉自動(dòng)刷新,待開(kāi)始使用該索引時(shí)荐糜,再把它們調(diào)回來(lái):
PUT /my_logs/_settings
{ "refresh_interval": -1 } //關(guān)閉實(shí)時(shí)更新
PUT /my_logs/_settings
{ "refresh_interval": "1s" }//開(kāi)啟每秒更新
refresh_interval 需要一個(gè) 持續(xù)時(shí)間 值巷怜, 例如 1s (1 秒) 或 2m (2 分鐘)葛超。 一個(gè)絕對(duì)值 1 表示的是 1毫秒 (會(huì)使你的集群陷入癱瘓)。
- 修改內(nèi)存緩存大小(indices.memory.index_buffer_size)延塑。
jvm內(nèi)存緩存的數(shù)據(jù)滿了或者是超過(guò)固定時(shí)間就會(huì)進(jìn)行刷新操作绣张,調(diào)整內(nèi)存緩存大小可以有效的降低刷新頻率
在elasticsearch.yml中可以這樣設(shè)置:
indices.memory.index_buffer_size: 20%(默認(rèn)是堆內(nèi)存的10%)
indices.memory.min_index_buffer_size: 96mb(默認(rèn)是48mb)
已經(jīng)索引好的文檔會(huì)先存放在內(nèi)存緩存中,等待被寫(xiě)到到段(segment)中页畦。緩存滿的時(shí)候會(huì)觸發(fā)段刷盤(pán)(吃i/o和cpu的操作)胖替。默認(rèn)最小緩存大小為48m,不太夠豫缨,最大為堆內(nèi)存的10%独令。對(duì)于大量寫(xiě)入的場(chǎng)景也顯得有點(diǎn)小。
- 修改事務(wù)日志(translog)的刷新頻率(fsync)(index.translog.sync_interval)和大泻冒拧(index.translog.flush_threshold_size)
日志中記錄了還在緩存中并未形成段的數(shù)據(jù)燃箭,會(huì)定時(shí)或者超過(guò)一定量后進(jìn)行刷新
在elasticsearch.yml中可以這樣設(shè)置:
index.translog.sync_interval:30s(默認(rèn)5s)。
index.translog.flush_threshold_size:700mb(默認(rèn)512mb)
index.translog.durability:async(默認(rèn)request) //通過(guò)異步提交日志舍败,不過(guò)可以會(huì)在宕機(jī)時(shí)丟失數(shù)據(jù)
- _id字段的使用招狸,應(yīng)盡可能避免自定義_id, 以避免針對(duì)ID的版本管理;建議使用ES的默認(rèn)ID生成策略或使用數(shù)字類型ID做為主鍵邻薯。
es讀性能優(yōu)化
1.合理的分片的數(shù)量裙戏,分片數(shù)量越多每個(gè)分片的數(shù)據(jù)范圍就越小,合理的分片數(shù)量能有效的提升每個(gè)分片的查詢性能
2. 遵循通用的原則厕诡, 4~32G的內(nèi)存給ES即可累榜,其余留給lucene。內(nèi)存對(duì)于 Elasticsearch 來(lái)說(shuō)絕對(duì)是重要的灵嫌,它可以被許多內(nèi)存數(shù)據(jù)結(jié)構(gòu)使用來(lái)提供更快的操作壹罚。但是另外一個(gè)內(nèi)存消耗大戶 非堆內(nèi)存 (off-heap)的Lucene是用于索引的關(guān)鍵
關(guān)閉交換分區(qū),防止內(nèi)存發(fā)生交換導(dǎo)致性能下降 通過(guò)執(zhí)行swapoff -a或者通過(guò): 在elasticsearch.yml 中 bootstrap.memory_lock: true寿羞, 以保持JVM鎖定內(nèi)存猖凛,保證ES的性能晃洒。
es的鎖機(jī)制
由于es需要處理一定的并發(fā)量的寫(xiě)操作修肠,es是使用的樂(lè)觀鎖,主要是使用java的CAS技術(shù)實(shí)現(xiàn)樂(lè)觀鎖
正排索引
就是利用文檔id查詢文檔內(nèi)容,也就是通過(guò)key去查value
倒排索引
就是通過(guò)value去查key,關(guān)于倒排索引這里有一篇不錯(cuò)的文章可以供大家參考https://blog.csdn.net/qq_21312297/article/details/102496833
es索引的過(guò)程
es是先通過(guò)term Dictionary將每個(gè)單詞出現(xiàn)在文檔的位置地址這個(gè)過(guò)程是倒排索引唉铜,然后通過(guò)地址去查詢文檔霞幅,這個(gè)是正排索引漠吻,es就是倒排索引和正排索引的結(jié)合term Dictionary(單詞字典):記錄了所有文檔的單詞,es儲(chǔ)存的文檔內(nèi)容越大詞典也就越大司恳,還記錄了單詞是放在哪些文檔上的關(guān)聯(lián)信息途乃,通常term Dictionary會(huì)被拆分成單詞的前綴組成一顆B+樹(shù),每個(gè)葉子節(jié)點(diǎn)的單詞會(huì)記錄著單詞所在文檔的位置地址
Posting List:記錄了單詞對(duì)應(yīng)文檔的集合扔傅,由Posting組成耍共,而Posting中包含了文檔id,單詞出現(xiàn)頻率烫饼,文檔中單詞的位置,單詞在文檔開(kāi)始和結(jié)束的位置
文檔字段類型
核心類型 字符串類型 string,text,keyword
整數(shù)類型 integer,long,short,byte
浮點(diǎn)類型 double,float,half_float,scaled_float
邏輯類型 boolean
日期類型 date
范圍類型 range
二進(jìn)制類型 binary
復(fù)合類型 數(shù)組類型 array
對(duì)象類型 object
嵌套類型 nested
地理類型 地理坐標(biāo)類型 geo_point
地理地圖 geo_shape
特殊類型 IP類型 ip
范圍類型 completion
令牌計(jì)數(shù)類型 token_count
附件類型 attachment
抽取類型 percolator
基礎(chǔ)語(yǔ)句
index操作
創(chuàng)建index:
put /index_name
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
查看index:
get /_cat/indices
刪除index:
delete /index_name
document操作
創(chuàng)建id為2的文檔:
DELETE /index_name/doc/2
創(chuàng)建id為1的文檔:
put /index_name/_doc/1
{
"name":"es",
"user":"test"
}
創(chuàng)建自帶id的文檔:
post /index_name/_doc/
{
"name":"es",
"user":"test"
}
_routing:
如果在創(chuàng)建mapping時(shí)設(shè)置了_routing為true,那么創(chuàng)建文檔的時(shí)候必須帶上routing,否則出錯(cuò):
post /index_name/_doc?routing=xxxxx
{
"name":"es",
"user":"test"
}
post /index_name/_doc/1?routing=xxxxx
{
"name":"es",
"user":"test"
}
批量創(chuàng)建文檔:
put /u/_bulk
{"index":{"_id":3}}
{"username":"james","code":23,"age":32,"country":"usa","job":"basketball"}
{"index":{"_id":4}}
{"username":"haden","code":15,"age":30,"country":"usa","job":"basketball"}
{"index":{"_id":5}}
{"username":"bingbing","code":999,"age":35,"country":"chn","job":"act"}
{"index":{"_id":6}}
{"username":"susu","code":999,"age":25,"country":"chn","job":"great"}
{"index":{"_id":7}}
{"username":"hu","code":999,"age":36,"country":"chn","job":"act"}
批量修改文檔:
POST _bulk
{"update":{"_index":"test","_type":"product","_id":1}}
{"doc":{ "price" : 5200, "productName" : "蘋(píng)果11","memory":"128G" }}
{"update":{"_index":"test","_type":"product","_id": 2 }}
{"doc":{ "price" : 3100, "productName" : "小米10","memory":"268G" }}
{"update":{"_index":"test","_type":"product", "_id": 3 }}
{"doc":{ "price" : 1300, "productName" : "酷派大神","memory":"16G" }}
{"update":{"_index":"test","_type":"product", "_id": 4 }}
{"doc":{ "price" : 730, "productName" : "魅藍(lán)note3","memory":"32G" }}
{"update":{"_index":"test","_type":"product", "_id": 6 }}
{"doc":{ "price" : 10000, "productName" : "macBook Pro","memory":"521G" }}
{"update":{"_index":"test","_type":"product", "_id": 7 }}
{"doc":{ "price" : 6500, "productName" : "華為P40","memory":"128G" }}
{"update":{"_index":"test","_type":"product","_id": 8 }}
{"doc":{ "price" : 3100, "productName" : "Ipad Air3","memory":"64G" }}
批量查詢:
post /_mget
{
"docs": [
{
"_index": "test_index",
"_type": "doc",
"_id": "1"
},
{
"_index": "test_index",
"_type": "doc",
"_id": "Ai9cM3IBEyMN0HxifBpI"
}
]
修改文檔:
POST /u/_doc/5/_update
{
"doc":{
"age":41,
"username":"kate"
}
}
根據(jù)查詢的結(jié)果更改文檔字段:
POST /u/_doc/_update_by_query
{
"script":{
"source":"ctx._source['brith']='1990-11-11 12:00:00'"
},
"query":{
"match_all":{
}
}
}
新增文檔字段:
PUT /u/_mapping
{
"properties":{
"brith":{
"type":"date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
分詞器
分詞就是將文本轉(zhuǎn)化為一系列單詞的過(guò)程试读,也叫做文本分析杠纵,在es中稱為Analysis,es默認(rèn)的Analysis是standard
Analysis由三部分組成:
Character Filters:對(duì)原始文本進(jìn)行處理,去掉一些特殊的符號(hào)標(biāo)簽钩骇,例如去除html的特殊標(biāo)記符
Tokenizer:將原始文本按照一定的規(guī)則切分成單詞
Toker Filters:對(duì)Tokenizer處理的單詞進(jìn)一步加工比藻,例如大小寫(xiě)轉(zhuǎn)換,刪除沒(méi)有意義的詞等
分詞器選擇并測(cè)試:
post /_analyze
{
"analyzer":"simple",//選擇simple分詞器
"text":"elasticsearch是世界最好的搜索引擎"
}
es內(nèi)置分詞器:
Standard - 默認(rèn)分詞器倘屹,按詞切分银亲,小寫(xiě)處理
Simple - 按照非字母切分(符號(hào)被過(guò)濾), 小寫(xiě)處理
Stop - 小寫(xiě)處理,停用詞過(guò)濾(the,a,is)
Whitespace - 按照空格切分纽匙,不轉(zhuǎn)小寫(xiě)
Keyword - 不分詞务蝠,直接將輸入當(dāng)作輸出
Patter - 正則表達(dá)式,默認(rèn)\W+(非字符分割)
Language - 提供了30多種常見(jiàn)語(yǔ)言的分詞器
Customer 自定義分詞器
中文分詞器:
IK - 支持中英文單詞分詞烛缔,支持ik_smart,ik_maxword的模式馏段,支持自定義詞庫(kù)、支持熱更新單詞詞典
jieba - python最流行的分詞器践瓷,支持繁體分詞院喜,自定義詞典等
Mapping
Mapping類似數(shù)據(jù)庫(kù)表數(shù)據(jù)類型定義,Mapping可以定義index下的字段名晕翠,字段類型够坐。mapping創(chuàng)建后不支持修改和刪除字段,只支持添加新字段
動(dòng)態(tài)mapping
在mapping中有dynamic屬性崖面,默認(rèn)是true,代表著動(dòng)態(tài)mapping梯影,在動(dòng)態(tài)mapping下我們插入的文檔巫员,es會(huì)為我們自動(dòng)識(shí)別文檔中的字段類型,然后為我們創(chuàng)建相應(yīng)的字段類型甲棍,下面是es自動(dòng)識(shí)別后為我們創(chuàng)建的字段類型動(dòng)態(tài)mapping可以降低用戶的使用es的成本
靜態(tài)mapping
當(dāng)我們創(chuàng)建mapping時(shí)并指定dynamic屬性為false简识,代表著靜態(tài)mapping,在靜態(tài)mapping下如果我們插入了mapping中沒(méi)有定義的字段就會(huì)自動(dòng)的進(jìn)行忽略感猛,忽略的意思就是插入沒(méi)有定義的字段可以正常插入七扰,但是搜索的時(shí)候會(huì)把字段給忽略了,查出來(lái)的結(jié)果不會(huì)包含mapping中不存在的字段并且這些字段也不支持索引
strict mapping
當(dāng)我們把mapping設(shè)置為strict時(shí)陪白,如果我們插入了mapping中沒(méi)有定義的字段就會(huì)直接報(bào)錯(cuò)
index設(shè)置
mapping字段中的index字段代表著是否可以用來(lái)做搜索颈走,默認(rèn)是true
null_values
mapping字段中的null_values字段代表著字段遇到null時(shí)做怎么樣的處理,es默認(rèn)字段遇到null時(shí)會(huì)自動(dòng)忽略
doc_values
字段的 doc_values 屬性有兩個(gè)值咱士, true立由、false轧钓。默認(rèn)為 true ,即開(kāi)啟锐膜。
當(dāng) doc_values 為 fasle 時(shí)毕箍,無(wú)法基于該字段排序、聚合道盏、在腳本中訪問(wèn)字段值而柑。
當(dāng) doc_values 為 true 時(shí),ES 會(huì)增加一個(gè)相應(yīng)的正排索引荷逞,這增加的磁盤(pán)占用媒咳,也會(huì)導(dǎo)致索引數(shù)據(jù)速度慢一些。
查看mapping
GET /index_name/_mapping
創(chuàng)建索引同時(shí)定義mapping
PUT /index_name
{
"settings": {
"number_of_shards": 4,
"number_of_replicas": 1
},
"mappings": {
"dynamic": "false",//定義mapping是否允許動(dòng)態(tài)生成颅围,默認(rèn)是true伟葫,還有一個(gè)strict,strict下插入沒(méi)有定義的字段會(huì)直接報(bào)錯(cuò)
"_routing": {
"required": true
},
"properties": {
"account": {
"type": "keyword"院促,
"null_values":"暫無(wú)" //遇到null時(shí)顯示為暫無(wú)筏养,es默認(rèn)遇到null會(huì)自動(dòng)忽略
},
"firstname": {
"type": "keyword"
},
"nikename": {
"type": "keyword"
},
"create_time":{
"type":"date",
"format":"MM/dd/yyyy"
},
"obj_id": {
"type": "keyword",
"index": false, //是否支持索引,默認(rèn)是true
"doc_values": false //false時(shí)不支持排序聚合
},
"bypass": {
"properties": {
"id": {
"type": "keyword"
},
"vpnmtype": {
"type": "keyword"
},
"vpnstype": {
"type": "keyword"
}
}
},
"caller_type": {
"type": "keyword"
},
"contend": {
"type": "text",
"fields": { //子字段類型常拓,索引時(shí)可以使用contend.keyword
"keyword": {
"type": "keyword"
}
},
"analyzer": "ik_smart"
},
.......
Search API
URI Search
q:指定URL查詢條件
df(default field):指定查詢的字段渐溶,如果不寫(xiě),es 會(huì)查詢所有字段或者是q中指定的字段
sort:排序
timeout:指定超時(shí)時(shí)間弄抬,默認(rèn)不超時(shí)
from茎辐,size:用于分頁(yè)
GET /u/_search?q=basketball
GET /u/_search?q=job:basketball mvp//查詢出所有job是basketball和mvp的文檔
GET /u/_search?q=job:"basketball mvp"http://查詢出所有job是basketball mvp的文檔
GET /u/_search?q=job:(basketball mvp)//查詢job:basketball或者job:mvp
GET /u/_search?q=user.id:8a4f500d
GET /u/_search?q=basketball&df=job&sort=age:asc&from=1&size=3&timeout=1s//df指定q的值basketball從job字段查,分頁(yè)從第一頁(yè)開(kāi)始掂恕,每頁(yè)3條記錄拖陆,查詢時(shí)間不能超過(guò)1秒,超過(guò)一秒就退出查詢
布爾操作:
要大寫(xiě)懊亡,不能小寫(xiě)
AND:&&
OR:||
NOT:!
GET /u/_search?q=basketball AND mvp //查詢出所有包含basketball 并且同時(shí)有mvp 的字段
GET /u/_search?q=job:(basketball AND mvp)//查詢出所有job是basketball并且有mvp的文檔
GET /u/_search?q=job:(basketball NOT mvp)//查詢出所有job是basketball并且沒(méi)有mvp的文檔
GET /u/_search?q=job:(basketball || mvp)//查詢出所有job是basketball或者有mvp的文檔
{
"profile":true"http://查看es查詢的過(guò)程
}
加減操作
+:在url寫(xiě)成%2B必須有 must
-:必須沒(méi)有 must_not
GET /u/_search?q=basketball %2Bmvp//查詢出所有是basketball 并且一定包含mvp的文檔
GET /u/_search?q=(basketball %2Bmvp)//查詢出所有是basketball 并且一定包含mvp的文檔
GET /u/_search?q=basketball -2Bmvp//查詢出所有是basketball 并且一定不包含mvp的文檔
GET /u/_search?q=job:(basketball -2Bmvp)//查詢出所有job是basketball 并且一定不包含mvp的文檔
范圍查詢
閉區(qū)間 [ ] 開(kāi)區(qū)間{ }
age:[1 TO 10]相當(dāng)于1<=age<=10
age:[1 TO 10}相當(dāng)于1<=age<10
age:[1 TO ]相當(dāng)于age>=1
age:[* TO 10]相當(dāng)于age<=10
GET /u/_search?q=basketball AND mvp age:>31 //查詢出所有包含basketball 并且同時(shí)有mvp 的字段或者age大于31
GET /u/_search?q=basketball AND mvp AND age:>31//查詢出所有包含basketball 并且同時(shí)有mvp 的字段并且age大于31
通配符查詢
username:j?mes:匹配任意一個(gè)字符
username:jam*:匹配任意多個(gè)字符
username:j*s:匹配任意多個(gè)字符
GET /u/_search?q=j*s
GET /u/_search?q=username:j*s
GET /u/_search?q=j?mes
wildcard
wildcard類似上的模糊查詢依啰,相應(yīng)于GET /u/_search?q=j*s的 DSL寫(xiě)法
post /u/_search
{
"query": {
"wildcard": {
"username.keyword":"j*s"
}
}
}
正則表達(dá)式查詢
這個(gè)需要對(duì)正則表達(dá)的掌握能力,舉兩個(gè)例子
GET /u/_search?q=username:/j.{1,}/
GET /u/_search?q=username:/[張李].*亭{1,}.*/
query DSL 的寫(xiě)法
post /u/_search
{
"query": {
"regexp": {
"username":"j.*"
}
}
}
模糊匹配查詢
GET /u/_search?q=job:basketball~1 //查詢job中與basketball相差1個(gè)char值的文檔店枣,例如basketball 速警、basketball mvp
近似度查詢
GET /u/_search?q=job:“basketball mvp“~1 //匹配到basketball mvp 前后中間可以允許插入1個(gè)詞 basketball xxxx mvp\basketball mvp xxxx\xxxx basketball mvp都會(huì)匹配到,
Request Body Search
query DSL
字段查詢
1鸯两、全文匹配
對(duì)text類型的字段查詢時(shí)闷旧,會(huì)先分詞
-
match:
分詞后詞語(yǔ)沒(méi)有先后順序,隨意組合钧唐,這個(gè)適合非常適用于關(guān)鍵詞全文檢索
select * from u where job like '%basketball%' or job like '%mvp%'
post /u/_search
{
"profile":true,//查看es查詢的過(guò)程
"query":{
"match":{
"job":"basketball mvp"http://job字段查詢即包含basketball 或者包含mvp的文檔
}
}
}
select * from u where job like '%basketball%' and job like '%mvp%'
post /u/_search
{
"query": {
"match":{
"job":{
"query":"basketball mvp",//job必須同時(shí)包含basketball和mvp
"operator":"and"http://默認(rèn)是or
}
}
}
}
post /u/_search
{
"query": {
"match":{
"job":{
"query":"basketball mvp act",
"minimum_should_match":"2"http://搜索出job字段中至少包含關(guān)鍵詞其中兩個(gè)才會(huì)匹配上
}
}
}
}
- match_all:
select * from u
post /u/_search
{
"query": {
"match_all": {}
}
}
-
match_phrase:
分詞后詞語(yǔ)存在先后順序- match_phrase還是分詞后去搜的
- 目標(biāo)文檔需要包含分詞后的所有詞
- 目標(biāo)文檔還要保持這些詞的相對(duì)順序和文檔中的一致
- match_phrase的缺點(diǎn)就是性能比較差
以"hello world"為例忙灼,要求結(jié)果中必須包含hello和world,而且還要求他們是連著的逾柿,順序也是固定的缀棍,hello that word不滿足宅此,world hello也不滿足條件。
post /u/_search
{
"query": {
"match_phrase":{
"job":"basketball mvp"http://查詢包含basketball mvp的文檔爬范,
//與term不同的是term是從索引的單詞找父腕,match_phrase從文檔的單詞找
}
}
}
post /u/_search
{
"query": {
"match_phrase":{
"job":{
"query":"basketball act",
"slop":"1"http://允許文檔出現(xiàn)和搜索條件相差一個(gè)距離的文檔
// 例如這里會(huì)匹配到 basketball xxxx act/basketball act xxxx/xxxx basketball act
}
}
}
}
-
query_string:
這個(gè)關(guān)鍵詞和match類似,只是query_string更加暴力是所有字段中搜索范圍更廣泛青瀑。match則是需要指定字段的搜索的璧亮。但是query_string也可以指定字段并且可以使用and or等關(guān)鍵詞,不指定字段默認(rèn)全字段搜索斥难,性能會(huì)很差
post /u/_search
{
"query": {
"query_string":{
"query":"basketball AND act"http://匹配所有的字段中即有basketball又有act的文檔
}
}
}
post /u/_search
{
"query": {
"query_string":{
"default_field":"job",//匹配job字段中即有basketball又有act的文檔
"query":"basketball AND act"
}
}
}
post /u/_search
{
"query": {
"query_string":{
"fields":["job","username"],//只匹配job和username字段,并且每個(gè)字段都必須包含james 和 act
"query":"james and act"
}
}
}
2枝嘶、精確查詢
- term、terms:將查詢語(yǔ)句作為一個(gè)單詞查詢哑诊,不做分詞處理,查詢時(shí)字段必須完全匹配包括長(zhǎng)度順序內(nèi)容群扶。使用這類關(guān)鍵詞時(shí)字段的類型不要使用text,應(yīng)當(dāng)使用keyword類型,如果字段是text類型的話镀裤,我們查詢時(shí)需要這樣寫(xiě): xxxx.keyword
select * from u where job="basketball mvp"
post /u/_search
{
"query": {
"term":{
"job.keyword":"basketball mvp"http://這里在倒排索引中匹配basketball mvp
//最終的結(jié)果是匹配不到任何文檔竞阐,因?yàn)樗饕卸际且粋€(gè)個(gè)被切分了的單詞不存在“basketball mvp”
}
}
}
select * from u where job in ('basketball', 'mvp')
post /u/_search
{
"query": {
"terms":{
"job.keyword":["basketball","mvp"]
}
}
}
3、范圍暑劝、排序骆莹、分頁(yè)
- range: 范圍查詢 lt:小于、lte:小于等于担猛、gt:大于幕垦、gte大于等于
select * from u where age between 30 and 40;
post /u/_search
{
"query" : {
"range" : {
"age" : {
"gte" : 30,
"lte" : 40
}
}
}
}
- sort,from,size:
POST /test/product/_search
{
"query":{
"match": {
"productName":"蘋(píng)果小米華為"
}
},
"sort":{"price":"desc"},
"from":2,
"size":3
}
scroll:深分頁(yè),對(duì)于上面介紹的淺分頁(yè),如果請(qǐng)求的頁(yè)數(shù)較少(假設(shè)每頁(yè)20個(gè)docs), Elasticsearch不會(huì)有什么問(wèn)題,但是如果頁(yè)數(shù)較大時(shí),比如請(qǐng)求第1000頁(yè)傅联,Elasticsearch不得不取出第1頁(yè)到第1000頁(yè)的所有docs先改,再去除第1頁(yè)到第999頁(yè)的docs,得到第1000頁(yè)的docs蒸走。解決的方式就是使用scroll盏道,scroll就是維護(hù)了當(dāng)前索引段的一份快照信息--緩存
初始化的時(shí)候就像是普通的search一樣 其中的scroll=3m代表當(dāng)前查詢的數(shù)據(jù)緩存3分鐘
POST test/_search?scroll=3m
{
"query":{
"match_all": {}
}
}
在遍歷時(shí)候,拿到上一次遍歷中的_scroll_id载碌,然后帶scroll參數(shù),3m代表重置過(guò)期時(shí)間
POST /_search/scroll
{
"scroll" : "3m",
"scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFjlxTWE1RTZwUmdpd3FZSkpsYm5kYXcAAAAAAAA-vxZBRWtUWDAyalM5YTZvbmx0YTJxQjZR"
}
相關(guān)性得分(_score)
依據(jù):
- 詞頻:單詞在該文檔出現(xiàn)的頻率越高,相關(guān)性越高
- 文檔長(zhǎng)度:文檔越短衅枫,相關(guān)性越高
- 包含單詞文檔數(shù)量:文檔包含某個(gè)單詞的數(shù)量越少嫁艇,相關(guān)性越高
復(fù)合查詢
constant_score:
默認(rèn)將其查詢結(jié)果的文檔得分都設(shè)置為1(如果不指定boost的話)或者指定boost的值,這個(gè)是當(dāng)我們不關(guān)心檢索詞頻率TF(Term Frequency)對(duì)搜索結(jié)果排序的影響時(shí)使用(簡(jiǎn)單了說(shuō)就是不在乎得分)
POST /test/product/_search
{
"query":{
"constant_score": {
"filter": {
"match":{
"productName":"華為"
}
},
"boost": 1
}
}
}
GET test_index/_search
{
"query": {
"constant_score": {
"boost": 1.0,
"filter": {
"bool": {
"must": [
{
"terms": {
"qq": [
"7823709637249",
"7828688362980"
]
}
}
]
}
}
}
}
}
bool:
-
filter:使用filter查詢時(shí)會(huì)有緩存,所以其效率很高弦撩,如果不使用相關(guān)性得分的排排序步咪,推薦使用filter
post /u/_search
{
"query": {
"bool": {
"filter": {
"term": {
"job.keyword": "basketball"
}
}
}
}
}
post /u/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"job": "basketball"
}
},
{
"match": {
"job": "act"
}
}
]
}
}
}
- must:
post /u/_search
//查詢文檔中的job字段必須同時(shí)包含basketball和act
{
"query": {
"bool": {
"must": [
{
"term": {
"job": "basketball"
}
},
{
"match": {
"job": "act"
}
}
]
}
}
}
- must_not:
post /u/_search
//查詢文檔中的job字段必須同時(shí)包含basketball和act,而要求必須不能有mvp
{
"query": {
"bool": {
"must": [
{
"term": {
"job": "basketball"
}
},
{
"match": {
"job": "act"
}
}
],
"must_not": [
{
"match": {
"job": "mvp"
}
}
]
}
}
}
- should:默認(rèn)至少滿足一個(gè)條件,可以通過(guò)minimum_should_match控制滿足個(gè)數(shù)
post /u/_search
//查詢滿足其中之一的查詢即可益楼,也就是job中包含basketball或者act或者mvp其中一個(gè)就能查詢出來(lái)
{
"query": {
"bool": {
"should": [
{
"term": {
"job": "basketball"
}
},
{
"match": {
"job": "act"
}
},
{
"match_phrase": {
"job": "basketball mvp"
}
}
]
}
}
}
post /u/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"job": "basketball"
}
},
{
"match": {
"job": "act"
}
},
{
"match_phrase": {
"job": "basketball mvp"
}
}
]猾漫,
"minimum_should_match":3//設(shè)置了滿足條件為3
//查詢結(jié)果同時(shí)滿足其中三個(gè)也就job中包含basketball并且包含act和mvp就能查詢出來(lái)都
}
}
}
- should與must\must_not:查詢時(shí)必須滿足或者必須不滿足must/must_not,可以不滿足should点晴,如果可以滿足should也一并查出
post /u/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"job": "act"
}
}
],
"must": [
{
"match":{
"job":"mvp"
}
}
]
}
}
}
should+must+filter
{
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{
"terms": {
"boost": 1.0,
"msisdn": [
"7823709637249",
"7828603061831",
"7827817096436"
]
}
},
{
"range": {
"ts_m": {
"from": 1583622000017,
"to": 1618902000017
}
}
},
{
"bool": {
"should": [
{
"terms": {
"app_id": [
"0"
],
"boost": 1.0
}
},
{
"terms": {
"host": [
"res.wx.qq.com",
"bluedot.is.autonavi.com.gds.alibabadns.com"
]
}
},
{
"match": {
"col10": {
"query": "品種貓 部門(mén) 蛾子 劉微球"
}
}
}
]
}
}
]
}
}
]
}
}
}
- source:只希望返回個(gè)別字段即可
//只希望查詢時(shí)返回username字段
GET /u/_search?_source=username
Count API
獲取符合查詢條件的文檔數(shù)量
查詢語(yǔ)句和上面的一樣只是把URL修改了
post /u/_count
{
"query": {
"bool": {
"should": [
{
"match": {
"job": "act"
}
}
],
"must": [
{
"match":{
"job":"mvp"
}
}
]
}
}
}
排序、分頁(yè)滾動(dòng)
sort
-
數(shù)字類型排序遍歷
單字段排序
post /u/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"job": "act"
}
}
],
"must": [
{
"match": {
"job": "mvp"
}
}
]
}
},
"sort": {
"age": "desc"http://按照年齡倒敘排序
}
}
多字段排序
post /u/_search
{
"query": {
"match": {
"job": "basketball"
}
},
"sort": [
{
"age": "desc"
},
{
"_score": "desc"
}
]
}
-
字符串類型排序
按照字符串類型排序時(shí)不能排序text類型的悯周,只能排序keyword的類型粒督,所以在排序text類型時(shí)可以使用text.keyword的方式或者使用設(shè)置fielddata的屬性,例如如下面的查詢
post /u/_search
//text.keyword的方式
{
"query": {
"match": {
"job": "basketball"
}
},
"sort": {
"username.keyword":"asc"
}
}
設(shè)置fielddata為true
post /u/_mapping
{
"properties":{
"job":{
"type":"text",
"fielddata": true
}
}
}
然后直接進(jìn)行text排序
POST /u/_search
{
"query": {
"match": {
"job": "basketball"
}
},
"sort": {
"job":"asc"
}
}
-
分頁(yè)
from:開(kāi)始位置 es默認(rèn)不超過(guò)過(guò)
size:獲取的總數(shù)
es默認(rèn)不支持深分頁(yè)換種說(shuō)法就是es不支持大容量的分頁(yè)禽翼,默認(rèn)from+size不能超過(guò)10000
post /u/_search
{
"from":9996,
"size":4//from或者size再設(shè)置大一點(diǎn)就會(huì)報(bào)錯(cuò)
}
-
Scroll 分頁(yè)滾動(dòng)屠橄、遍歷
利用Scroll可以改變分頁(yè)查詢中不能做深分頁(yè)的缺點(diǎn),Scroll查詢方式的原理就是通過(guò)每次查詢后闰挡,返回一個(gè)scroll_id锐墙。根據(jù)這個(gè)scroll_id 進(jìn)行下一頁(yè)的查詢〕ば铮可以把這個(gè)scroll_id理解為通常關(guān)系型數(shù)據(jù)庫(kù)中的游標(biāo)溪北。scroll查詢的數(shù)據(jù)是當(dāng)前索引段的一份快照信息–緩存,所以scroll沒(méi)有實(shí)時(shí)性
//創(chuàng)建一個(gè)scroll設(shè)置夺脾,并且設(shè)置存活時(shí)間是兩分鐘之拨,也就是快照存活2分鐘
GET /u/_search?scroll=2m
{
"query": {"match_all": {}},
"size": 1//設(shè)置每次滾動(dòng)取1條數(shù)據(jù),結(jié)果會(huì)返回
}
拿著scroll_id可以進(jìn)行滾動(dòng)
//滾動(dòng)scroll
POST /_search?scroll
{
"scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAANAWb1IxVjQ0cFBUMy1jb1dFZUdRbDNKdw==",
"scroll":"5m"
}
-
Search After分頁(yè)滾動(dòng)、遍歷
利用Search After可以解決Scroll不能實(shí)時(shí)滾動(dòng)的缺點(diǎn)劳翰,但是Search After只能往下滾動(dòng)敦锌,只支持向下滾動(dòng),不支持向上滾動(dòng)佳簸,并且創(chuàng)建Search After必須要給文檔排序
post /u/_search
{
"size":1,
"sort":{
"age":"desc"
}
}
將返回結(jié)果的sort中的值設(shè)置到滾動(dòng)語(yǔ)句中乙墙,上圖是56,設(shè)置search_after為56
GET /u/_search
{
"size":1,
"search_after":[56],
"sort":{
"age":"desc"
}
}
總結(jié)分頁(yè)的使用場(chǎng)景
Aggregation 聚合查詢
格式:多用于統(tǒng)計(jì)使用的生均,舉個(gè)例子
例如統(tǒng)計(jì)從事各類職業(yè)的人數(shù)有多少
GET /u/_search
{
"size": 0,
"aggs": {
"tj": {
"terms": {
"field": "job.keyword"
}
}
}
}
返回結(jié)果
"aggregations": {
"tj": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 2,
"buckets": [
{
"key": "act",
"doc_count": 2
},
{
"key": "act av",
"doc_count": 2
},
{
"key": "basketball",
"doc_count": 2
},
........
]
}
}
聚合查詢做的就是類似上面的事情听想,聚合查詢分為4大類分別為:
- Bucket:分析統(tǒng)計(jì)類型,類似數(shù)據(jù)庫(kù)的group by
- Metric:指標(biāo)類型,統(tǒng)計(jì)如最大值马胧,最小值汉买,平均值等
- Pipeline:管道分析類型,基于上一級(jí)分析的結(jié)果進(jìn)行再次分析
- Matrix:矩陣分析類型佩脊,是es的多維度分析
Bucket
bucket的作用類似數(shù)據(jù)庫(kù)的分組蛙粘,把不同的分析結(jié)果裝到幾個(gè)桶里
- terms:按照詞語(yǔ)分桶威彰,分桶字段如果是keyword不會(huì)進(jìn)行分詞慨代,直接按照整個(gè)單詞分桶债鸡,如果是text則會(huì)先分詞在分桶晶密,不過(guò)使用text進(jìn)行聚合需要設(shè)置fielddata為true
GET /u/_search
{
"aggs": {
"aggs_bulk": {
"terms": {
"field": "job.keyword",
"size":3//指定返回的個(gè)數(shù)
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_bulk": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 11,
"buckets": [
{
"key": "act",
"doc_count": 2
},
{
"key": "act av",
"doc_count": 2
},
{
"key": "basketball",
"doc_count": 2
}
]
}
}
-
range
范圍聚合,統(tǒng)計(jì)數(shù)據(jù)指定范圍的數(shù)量
GET /u/_search
{
"aggs": {
"aggs_range": {
"range": {
"field": "age",
"ranges": [
{
"to": 36//統(tǒng)計(jì)年齡小于36的人數(shù)
},
{
"from": 35,
"to": 41
}//統(tǒng)計(jì)年齡35.0-41.0之間的人數(shù)
]
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_range": {
"buckets": [
{
"key": "*-36.0",
"to": 36.0,
"doc_count": 9
},
{
"key": "35.0-41.0",
"from": 35.0,
"to": 41.0,
"doc_count": 7
}
]
}
}
-
date range
指定日期范圍的分桶
GET monitor_temp/_search
{
"aggs": {
"aggs_range": {
"date_range": {
"field": "ts_m",
"format":"yyyy-MM-dd HH:mm:ss",
"ranges": [
{
"from":"2020-04-01 00:00:00",
"to": "2020-04-30 12:00:00"
},
{
"from":"2020-05-01 00:00:00",
"to": "2020-05-30 12:00:00"
}
]
}
}
}
}
返回部分結(jié)果
"aggregations" : {
"aggs_range" : {
"buckets" : [
{
"key" : "2020-04-01 00:00:00-2020-04-30 12:00:00",
"from" : 1.5856992E12,
"from_as_string" : "2020-04-01 00:00:00",
"to" : 1.588248E12,
"to_as_string" : "2020-04-30 12:00:00",
"doc_count" : 3
},
{
"key" : "2020-05-01 00:00:00-2020-05-30 12:00:00",
"from" : 1.5882912E12,
"from_as_string" : "2020-05-01 00:00:00",
"to" : 1.59084E12,
"to_as_string" : "2020-05-30 12:00:00",
"doc_count" : 3
}
]
}
}
-
histogram
統(tǒng)計(jì)固定間隔的數(shù)據(jù)數(shù)量。類似一個(gè)樹(shù)形柱狀圖
GET /u/_search
{
"aggs": {
"aggs_his": {
"histogram": {
"field": "age",
"interval":5,//統(tǒng)計(jì)年齡間隔5歲的各個(gè)階段的人數(shù)
"extended_bounds": //查詢范圍
{
"min":30,
"max": 56
}
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_his": {
"buckets": [
{
"key": 25.0,
"doc_count": 2
},
{
"key": 30.0,
"doc_count": 6
},
{
"key": 35.0,
"doc_count": 7
},
{
"key": 40.0,
"doc_count": 1
},
{
"key": 45.0,
"doc_count": 0
},
{
"key": 50.0,
"doc_count": 0
},
{
"key": 55.0,
"doc_count": 1
}
]
}
}
從query的結(jié)果集中匙头,以ts_m字段指定的范圍蝙叛,取每隔1小時(shí)取一次數(shù)據(jù)量統(tǒng)計(jì)
GET monitor_temp/_search
{
"query": {
"range": {
"ts_m": {
"gte": 1617273000000,
"lte": 1617359400000
}
}
},
"aggs": {
"aggs_his": {
"histogram": {
"field": "ts_m",
"format":"yyyy-MM-dd HH:mm",
"interval":3600000,
"extended_bounds":
{
"max":1617359400000,
"min":1617273000000
}
}
}
}
}
返回的部分結(jié)果
"aggregations" : {
"aggs_his" : {
"buckets" : [
{
"key_as_string" : "2021-04-01 10:00",
"key" : 1.6172712E12,
"doc_count" : 0
},
{
"key_as_string" : "2021-04-01 11:00",
"key" : 1.6172748E12,
"doc_count" : 0
},
{
"key_as_string" : "2021-04-01 12:00",
"key" : 1.6172784E12,
"doc_count" : 0
},
{
"key_as_string" : "2021-04-01 13:00",
"key" : 1.617282E12,
"doc_count" : 0
},
{
"key_as_string" : "2021-04-01 14:00",
"key" : 1.6172856E12,
"doc_count" : 0
},
{
"key_as_string" : "2021-04-01 15:00",
"key" : 1.6172892E12,
"doc_count" : 0
},
.......
]
}
}
-
date histogram
用于日期的histogram
GET /u/_search
{
"aggs": {
"aggs_his": {
"date_histogram": {
"field": "brith",
"interval":"year",//出生日期以每一年為間隔
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}
}
輸出結(jié)果
"aggregations": {
"aggs_his": {
"buckets": [
{
"key_as_string": "1954-01-01 00:00:00",
"key": -504921600000,
"doc_count": 1
},
{
"key_as_string": "1959-01-01 00:00:00",
"key": -347155200000,
"doc_count": 0
},
{
"key_as_string": "1967-01-01 00:00:00",
"key": -94694400000,
"doc_count": 0
},
{
"key_as_string": "1968-01-01 00:00:00",
"key": -63158400000,
"doc_count": 0
},
{
"key_as_string": "1969-01-01 00:00:00",
"key": -31536000000,
"doc_count": 0
},
.................
從query的結(jié)果集中展融,以ts_m字段指定的范圍指么,取每隔1小時(shí)取一次數(shù)據(jù)量統(tǒng)計(jì),返回的結(jié)果是上海時(shí)間
GET monitor_temp/_search
{
"aggregations": {
"aggs_his": {
"date_histogram": {
"extended_bounds": {
"max":1617359400000,
"min":1617273000000
},
"field": "ts_m",
"interval": "1h",
"offset": 0,
"format":"MM-dd HH:mm",
"order": {
"_key": "asc"
},
"time_zone": "Asia/Shanghai"
}
}
},
"query": {
"range": {
"ts_m": {
"from": 1617273000000,
"to": 1617359400000
}
}
}
}
部分返回結(jié)果
"aggregations" : {
"aggs_his" : {
"buckets" : [
{
"key_as_string" : "04-01 18:00",
"key" : 1617271200000,
"doc_count" : 0
},
{
"key_as_string" : "04-01 19:00",
"key" : 1617274800000,
"doc_count" : 0
},
{
"key_as_string" : "04-01 20:00",
"key" : 1617278400000,
"doc_count" : 0
},
{
"key_as_string" : "04-01 21:00",
"key" : 1617282000000,
"doc_count" : 0
},
{
"key_as_string" : "04-01 22:00",
"key" : 1617285600000,
"doc_count" : 0
},
Metric
- 單值分析
分析只輸出一個(gè)結(jié)果
- min酝惧、max、avg伯诬、sum
//查詢age的最小值
GET test/_search
{
"aggs": {
"max": {
"min": {
"field": "price"
}
}
}
}
輸出部分結(jié)果
"aggregations" : {
"max" : {
"value" : 130.0
}
//查詢age的最大值
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_name": {
"max": {
"field": "age"
}
}
}
}
//查詢age的總值
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_name": {
"sum": {
"field": "age"
}
}
}
}
//查詢age的平均值
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_name": {
"avg": {
"field": "age"
}
}
}
}
可以將他們組合在一起
GET test/_search
{
"size": 0,
"aggs": {
"aggs_avg": {
"avg": {
"field": "price"
}
},
"aggs_sum": {
"sum": {
"field": "price"
}
},
"aggs_max": {
"max": {
"field": "price"
}
},
"aggs_min": {
"min": {
"field": "price"
}
}
}
}
輸出部分結(jié)果
"aggregations" : {
"aggs_sum" : {
"value" : 134633.0
},
"aggs_min" : {
"value" : 130.0
},
"aggs_avg" : {
"value" : 5853.608695652174
},
"aggs_max" : {
"value" : 22788.0
}
}
- cardinality:統(tǒng)計(jì)某個(gè)字段有多少種類
GET test/_search
{
"size": 0,
"aggs": {
"aggs_cardinality": {
"cardinality": {
"field": "productName.keyword" //統(tǒng)計(jì)productName的不同種類
}
}
}
}
部分輸出結(jié)果
"aggregations" : {
"aggs_cardinality" : {
"value" : 23
}
}
- 多值分析
分析可以輸出多個(gè)結(jié)果
stats晚唇、extended_stats、percentiles:
- stats:返回一系列統(tǒng)計(jì)類型盗似,包括min,max,avg,sum,count
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_stats": {
"stats": {
"field": "age"
}
}
}
}
輸出的結(jié)果
"aggregations": {
"aggs_count": {
"count": 17,
"min": 25.0,
"max": 56.0,
"avg": 34.64705882352941,
"sum": 589.0
}
}
- extended_stats:計(jì)算方差哩陕、標(biāo)準(zhǔn)差等使用extended_stats,是對(duì)stats功能的擴(kuò)展
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_estats": {
"extended_stats": {
"field": "age"
}
}
}
}
輸出結(jié)果
"aggregations": {
"aggs_estats": {
"count": 17,
"min": 25.0,
"max": 56.0,
"avg": 34.64705882352941,
"sum": 589.0,
"sum_of_squares": 21175.0,
"variance": 45.16955017301028,
"std_deviation": 6.720829574763094,
"std_deviation_bounds": {
"upper": 48.0887179730556,
"lower": 21.205399674003225
}
}
}
- percentiles:統(tǒng)計(jì)數(shù)據(jù)的所占百分位比重,例如統(tǒng)計(jì)數(shù)據(jù)中百分之多少的人是在哪個(gè)年齡段
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_percentile": {
"percentiles": {
"field": "age"
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_percentile": {
"values": {
"1.0": 24.999999999999996,//24歲年齡段的有百分之1
"5.0": 25.0,//25歲年齡段的有百分之5
"25.0": 31.0,//31歲年齡段的有百分之25
"50.0": 35.0,//35歲年齡段的有百分之50
"75.0": 36.0,//36歲年齡段的有百分之75
"95.0": 50.74999999999998,//51歲年齡段的有百分之95
"99.0": 56.0//56歲年齡段的有百分之99
}
}
}
我們可以指定某個(gè)百分?jǐn)?shù)范圍內(nèi)對(duì)應(yīng)的數(shù)值是哪些
GET /u/_search
{
"size": 0,
"aggs": {
"aggs_percentile": {
"percentiles": {
"field": "age",
"percents":[50,75]
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_percentile": {
"values": {
"50.0": 35.0,
"75.0": 36.0
}
}
}
- aggs_percentile:我們查某些數(shù)據(jù)范圍中是處于哪個(gè)百分位
GET test/_search
{
"aggs": {
"p_r": {
"percentile_ranks": {
"field": "price",
"values": [
19988,
5800
]
}
}
}
}
輸出結(jié)果
"aggregations" : {
"p_r" : {
"values" : {
"5800.0" : 63.47826086956522,
"19988.0" : 94.54434671825976
}
}
}
- top_hits:我們希望能從分組統(tǒng)計(jì)的基礎(chǔ)上再獲取統(tǒng)計(jì)信息
下面是按照職業(yè)進(jìn)行分組赫舒,但是我們要取每個(gè)分組中前十名
GET /u/_search
{
"size": 0,
"aggs": {
"tj": {
"terms": {
"field": "job.keyword"
},
"aggs": {
"my_top": {
"top_hits": {
"size": 10,
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
}
}
}
}
}
-
桶中桶 bucket+Metric的組合拳
在分組后悍及,對(duì)每個(gè)組在進(jìn)行統(tǒng)計(jì)
GET /u/_search
//統(tǒng)計(jì)在職業(yè)分組后,再統(tǒng)計(jì)每組職業(yè)的年齡段占比多少
{
"aggs": {
"aggs_term": {
"terms": {
"field": "job.keyword",
"size": 10
},
"aggs": {
"aggs_percentile": {
"percentiles": {
"field": "age"
}
}
}
}
}
}
返回結(jié)果
"aggregations": {
"aggs_term": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 2,
"buckets": [
{
"key": "act",
"doc_count": 2,
"aggs_percentile": {
"values": {
"1.0": 36.0,
"5.0": 36.0,
"25.0": 36.0,
"50.0": 38.5,
"75.0": 41.0,
"95.0": 41.0,
"99.0": 41.0
}
}
},
{
"key": "act av",
"doc_count": 2,
"aggs_percentile": {
"values": {
"1.0": 25.0,
"5.0": 25.0,
"25.0": 25.0,
"50.0": 30.0,
"75.0": 35.0,
"95.0": 35.0,
"99.0": 35.0
}
}
},
{
"key": "basketball",
"doc_count": 2,
"aggs_percentile": {
"values": {
"1.0": 30.999999999999996,
"5.0": 31.0,
"25.0": 31.0,
"50.0": 31.5,
"75.0": 32.0,
"95.0": 32.0,
"99.0": 32.0
}
}
},
{
"key": "basketball mvp",
"doc_count": 2,
"aggs_percentile": {
"values": {
"1.0": 29.999999999999996,
"5.0": 30.0,
"25.0": 30.0,
"50.0": 31.0,
"75.0": 32.0,
"95.0": 32.0,
"99.0": 32.0
}
}
},
{
"key": "basketball mvp act",
"doc_count": 2,
"aggs_percentile": {
"values": {
"1.0": 30.999999999999996,
"5.0": 31.0,
"25.0": 31.0,
"50.0": 43.5,
"75.0": 56.0,
"95.0": 56.0,
"99.0": 56.0
}
}
},
{
"key": "basketball act",
"doc_count": 1,
"aggs_percentile": {
"values": {
"1.0": 33.0,
"5.0": 33.0,
"25.0": 33.0,
"50.0": 33.0,
"75.0": 33.0,
"95.0": 33.0,
"99.0": 33.0
}
}
},
{
"key": "cartoonman hai",
"doc_count": 1,
"aggs_percentile": {
"values": {
"1.0": 36.0,
"5.0": 36.0,
"25.0": 36.0,
"50.0": 36.0,
"75.0": 36.0,
"95.0": 36.0,
"99.0": 36.0
}
}
},
.............
]
}
-
Pipeline管道聚合分析
針對(duì)上層分析的結(jié)果進(jìn)行再次分析接癌,其分析的結(jié)果會(huì)輸出到上層的結(jié)果中心赶,根據(jù)輸出的位置不同分為兩類:
-
內(nèi)嵌到上層的結(jié)果中
min、max扔涧、avg园担、stats、percentiles
min_bucket\max_bucket\avg_bucket\stats_bucket\percentiles_bucket
用法差不多枯夜,舉一個(gè)例子弯汰,
//計(jì)算每一類職業(yè)的平均收入,然后找出平均收入最低的職業(yè)
GET /u/_search
{
"aggs": {
"aggs_term": {
"terms": {
"field": "job.keyword"
},
"aggs": {
"aggs_avg": {
"avg": {
"field": "income"
}
}
}
},
"min_pipeline": {//給pipeline起名字湖雹,pipeline與aggs的子項(xiàng)aggs_term同級(jí),導(dǎo)致后面的buckets_path要寫(xiě)成aggs_term>aggs_avg
//分析誰(shuí)就與誰(shuí)同級(jí)
"min_bucket": {//min_bucket是關(guān)鍵詞咏闪,如果是算最大值換成max_bucket,平均值換成avg_bucket、同時(shí)獲取多個(gè)指標(biāo)則用stats_bucket
"buckets_path": "aggs_term>aggs_avg"http://aggs的所屬結(jié)構(gòu)
}
}
}
}
輸出結(jié)果
"min_pipeline": {
"value": 1000.0,//平均收入最低是1000
"keys": [//這幾個(gè)職業(yè)都是收入最低的
"cartoonman hai",
"cartoonman hot",
"cartoonman qun",
"cartoonman seven"
]
}
結(jié)果與上層的結(jié)果同級(jí)
-
聚合分析的范圍
aggs與query關(guān)鍵字同級(jí)摔吏,在query執(zhí)行后鸽嫂,aggs針對(duì)query執(zhí)行的結(jié)果進(jìn)行分析,也就是說(shuō)query查出來(lái)結(jié)果就是aggs的分析范圍
也可以在aggs內(nèi)部使用filter關(guān)鍵詞限定范圍
GET /u/_search
{
"aggs": {
"aggs_filter": {
"filter": {//利用filter限定aggs范圍
"match": {
"job":"basketball"
}
},
"aggs":{
"job_aggs":{
"terms":{
"field":"job.keyword"
}
}
}
}
}
}
還要一種限定范圍的方法是post_filter在aggs分析之后在進(jìn)行篩選
{
"aggs": {
"job_aggs": {
"terms": {
"field": "job.keyword"
}
}
},
"post_filter":{
"match":{
"job.keyword":"mvp"
}
}
}
聚合排序sort
GET /u/_search
{
"aggs": {
"aggs_term": {
"terms": {
"field": "job.keyword",
"order":{
"aggs_avg":"desc"http://以子聚合分析的結(jié)果排序
}
},
"aggs": {
"aggs_avg": {
"avg": {
"field": "income"
}
}
}
}
}
}
返回結(jié)果
"buckets": [
{
"key": "soccerball mvp",
"doc_count": 1,
"aggs_avg": {
"value": 5.0E8
}
},
{
"key": "basketball mvp",
"doc_count": 2,
"aggs_avg": {
"value": 1.3E8
}
},
{
"key": "basketball",
"doc_count": 2,
"aggs_avg": {
"value": 8.5E7
}
},
{
"key": "act",
"doc_count": 2,
"aggs_avg": {
"value": 1.01E7
}
},
{
"key": "basketball mvp act",
"doc_count": 2,
"aggs_avg": {
"value": 750000.0
}
},
{
"key": "basketball act",
"doc_count": 1,
"aggs_avg": {
"value": 600000.0
}
},
{
"key": "act av",
"doc_count": 2,
"aggs_avg": {
"value": 40000.0
}
},
{
"key": "great",
"doc_count": 1,
"aggs_avg": {
"value": 8000.0
}
},
.........................
以外層的key或者聚合分析數(shù)排序
GET /u/_search
{
"aggs": {
"aggs_term": {
"terms": {
"field": "job.keyword",
"order": [
{
"_key": "desc"http://聚合結(jié)果的key排序
},
{
"_count": "desc"http://聚合數(shù)量排序
}
]
},
"aggs": {
"aggs_avg": {
"avg": {
"field": "income"
}
}
}
}
}
}
返回結(jié)果
"buckets": [
{
"key": "soccerball mvp",
"doc_count": 1,
"aggs_avg": {
"value": 5.0E8
}
},
{
"key": "great",
"doc_count": 1,
"aggs_avg": {
"value": 8000.0
}
},
{
"key": "cartoonman seven",
"doc_count": 1,
"aggs_avg": {
"value": 1000.0
}
},
{
"key": "cartoonman qun",
"doc_count": 1,
"aggs_avg": {
"value": 1000.0
}
},
{
"key": "cartoonman hot",
"doc_count": 1,
"aggs_avg": {
"value": 1000.0
}
},
{
"key": "cartoonman hai",
"doc_count": 1,
"aggs_avg": {
"value": 1000.0
}
},
..........................