注意點(diǎn):現(xiàn)在kibana/elasticsearch最新版本為7.0,與5.2.0的語(yǔ)法有出入,需要注意
語(yǔ)法,自己查詢
kibana為操作elasticserch的界面,地址可以在啟動(dòng)日志中看到:

界面展示:

一下為一些操作練習(xí):
寫(xiě)入
PUT /ecommerce/product/1
{
"name" : "gaolujie yagao",
"desc" : "gaoxiao meibai",
"price" : 30,
"producer" : "gaolujie producer",
"tags": [ "meibai", "fangzhu" ]
}
寫(xiě)入
PUT /ecommerce/product/2
{
"name" : "jiajieshi yagao",
"desc" : "youxiao fangzhu",
"price" : 25,
"producer" : "jiajieshi producer",
"tags": [ "fangzhu" ]
}
寫(xiě)入
PUT /ecommerce/product/3
{
"name" : "zhonghua yagao",
"desc" : "caoben zhiwu",
"price" : 40,
"producer" : "zhonghua producer",
"tags": [ "qingxin" ]
}
查詢所有
GET /ecommerce/product/_search
{
"query": {
"match_all": {}
}
}
查詢name中帶有yagao的數(shù)據(jù)
GET /ecommerce/product/_search
{
"query": {
"match": {
"name": "yagao"
}
}
}
查詢name為yagao并且按照price降序排序
GET /ecommerce/product/_search
{
"query": {
"match": {
"name":"yagao"
}
},
"sort":[
{
"price":"desc"
}
]
}
分頁(yè)查詢,只查詢一條
GET /ecommerce/product/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 1
}
只查詢price與name
GET /ecommerce/product/_search
{
"query":{
"match_all": {}
},
"_source": ["price","name"]
}
查詢name中匹配價(jià)格大于30牙膏
GET /ecommerce/product/_search
{
"query": {
"bool": {
"must": [
{"match": {
"name": "yagao"
}}
],
"filter": {
"range": {
"price": {
"gt": 30
}
}
}
}
}
}
全文檢索
GET /ecommerce/product/_search
{
"query": {
"match": {
"producer": "yagao producer"
}
}
}
短語(yǔ)短語(yǔ)匹配
GET /ecommerce/product/_search
{
"query": {
"match_phrase": {
"producer": "jiajieshi producer"
}
}
}
高亮顯示xianshi高亮顯示顯示producer
GET /ecommerce/product/_search
{
"query": {
"match": {
"producer": "yagao producer"
}
},
"highlight": {
"fields": {
"producer": {}
}
}
}
將文本field的fielddata屬性設(shè)置為true
PUT /ecommerce/_mapping/product
{
"properties": {
"tags": {
"type": "text",
"fielddata": true
}
}
}
計(jì)算每個(gè)tag下的商品數(shù)量
GET /ecommerce/product/_search
{
"size": 0,
"aggs": {
"group_by_tags": {
"terms": {
"field": "tags"
}
}
}
}
對(duì)名稱(chēng)中包含yagao的商品,計(jì)算每個(gè)tag下的商品數(shù)量
GET /ecommerce/product/_search
{
"query": {
"match": {
"name": "yagao"
}
},
"aggs": {
"all_tags": {
"terms": {
"field": "tags"
}
}
}
}
先分組,再算每組的平均值,計(jì)算每個(gè)tag下的商品的平均價(jià)格
GET /ecommerce/product/_search
{
"size": 0,
"aggs": {
"group_by_tags": {
"terms": {
"field": "tags"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
計(jì)算每個(gè)tag下的商品的平均價(jià)格,并且按照平均價(jià)格降序排序
GET /ecommerce/product/_search
{
"size": 0,
"aggs": {
"group_by_tags": {
"terms": {
"field": "tags",
"order": {
"avg_price": "desc"
},
"size": 10
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
按照指定的價(jià)格范圍區(qū)間進(jìn)行分組,然后在每組內(nèi)再按照tag進(jìn)行分組,最后再計(jì)算每組的平均價(jià)格
GET /ecommerce/product/_search
{
"size": 0,
"aggs": {
"group_by_price": {
"range": {
"field": "price",
"ranges": [
{
"from": 0,
"to": 20
},
{
"from": 20,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"group_by_tags": {
"terms": {
"field": "tags"
},
"aggs": {
"average_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
}
}
es自動(dòng)生成id,使用的是GUID的算法,可以避免同一時(shí)間,不同節(jié)點(diǎn),同時(shí)創(chuàng)建索引id的時(shí)候造成id相同的情況,語(yǔ)法如下:
POST /test_index/my_test
{
"test":"mytest2"
}
結(jié)果如下:

定制返回結(jié)果
_source元數(shù)據(jù):就是說(shuō),我們?cè)趧?chuàng)建一個(gè)document的時(shí)候,使用的那個(gè)放在request body中的json串,默認(rèn)情況下,在get的時(shí)候,會(huì)原封不動(dòng)的給我們返回回來(lái)
PUT /test_index/my_test/1
{
"test1":"test1",
"test2":"test2"
}
GET /test_index/my_test/1?_source=test1
結(jié)果如下:

document的全量替換
1) 語(yǔ)法與創(chuàng)建文檔是一樣的,如果document id不存在,那么就創(chuàng)建;如果document id已經(jīng)存在,那么就是全量替換操作,替換document的json串內(nèi)容
2) document是不可變的,如果要修改document的內(nèi)容,第一種方式就是全量替換,直接對(duì)document重新建立索引,替換里面所有的內(nèi)容
3) es會(huì)將老的document標(biāo)記為deleted,然后新增我們給定的一個(gè)document,當(dāng)我們創(chuàng)建的越來(lái)越多的document的時(shí)候,es會(huì)在適當(dāng)?shù)膶?shí)際在后臺(tái)自動(dòng)刪除標(biāo)記為deleted的document
document的強(qiáng)制創(chuàng)建
1) 創(chuàng)建文檔與圈梁替換的語(yǔ)法一樣,有時(shí)我們只是想新建文檔,不想替換文檔,如果強(qiáng)制進(jìn)行創(chuàng)建呢?
2) PUT /index/type/id?op_type=create 或者 PUT /index/type/id/_create
最終結(jié)果:

document的刪除
DELETE /index/type/id
不會(huì)理解為為例刪除,只會(huì)將其標(biāo)記為deleted,當(dāng)數(shù)據(jù)越來(lái)越多的時(shí)候,在后臺(tái)自動(dòng)刪除
上機(jī)演練基于_version進(jìn)行樂(lè)觀鎖的并發(fā)控制
開(kāi)兩個(gè)kibana客戶端
PUT /test_index/my_test/7
{
"test_str":"test001"
}

PUT /test_index/my_test/7?version=1
{
"test_str":"test002"
}

另外一個(gè)客戶端,嘗試基于version=1的版本進(jìn)行修改,同樣帶上version版本號(hào),進(jìn)行樂(lè)觀鎖的并發(fā)控制:
PUT /test_index/my_test/7?version=1
{
"test_str":"test001"
}

商機(jī)動(dòng)手實(shí)戰(zhàn)演練基于external version進(jìn)行樂(lè)觀鎖并發(fā)控制
es提供了一個(gè)feature,就是說(shuō),你可以不用它提供的內(nèi)部的_version版本號(hào)來(lái)進(jìn)行并發(fā)控制,可以基于自己維護(hù)的一個(gè)版本號(hào)進(jìn)行并發(fā)控制。舉個(gè)例子,假如你的數(shù)據(jù)在mysql中也有一份,然后你的應(yīng)用系統(tǒng)本身就維護(hù)了一個(gè)版本號(hào),無(wú)論是什么自己生成的,程序控制的。這個(gè)時(shí)候,你進(jìn)行樂(lè)觀鎖并發(fā)控制的時(shí)候,可能并不是想要用es內(nèi)部的_version來(lái)進(jìn)行控制,而是用你自己維護(hù)的那個(gè)version來(lái)進(jìn)行控制。
原先的語(yǔ)法:url?version=1
現(xiàn)在的語(yǔ)法:url?version=1&version_type=external
version_type=external,唯一的區(qū)別在于,_version,只有當(dāng)你提供的version與es中的_version一模一樣的時(shí)候,才可以進(jìn)行修改,只要不一樣,就報(bào)錯(cuò);當(dāng)version_type=external的時(shí)候,只有當(dāng)你提供的version比es中的_version大的時(shí)候,才能完成修改
es,_version=1,?version=1,才能更新成功
es,_version=1,?version>1&version_type=external,才能成功,比如說(shuō)?version=2&version_type=external
partial update實(shí)現(xiàn)原理、手動(dòng)實(shí)踐
1、什么是partial update?
PUT /index/type/id,創(chuàng)建文檔&替換文檔,就是一樣的語(yǔ)法
一般對(duì)應(yīng)到應(yīng)用程序中,每次的執(zhí)行流程基本是這樣的:
(1)應(yīng)用程序先發(fā)起一個(gè)get請(qǐng)求,獲取到document,展示到前臺(tái)界面,供用戶查看和修改
(2)用戶在前臺(tái)界面修改數(shù)據(jù),發(fā)送到后臺(tái)
(3)后臺(tái)代碼,會(huì)將用戶修改的數(shù)據(jù)在內(nèi)存中進(jìn)行執(zhí)行,然后封裝好修改后的全量數(shù)據(jù)
(4)然后發(fā)送PUT請(qǐng)求,到es中,進(jìn)行全量替換
(5)es將老的document標(biāo)記為deleted,然后重新創(chuàng)建一個(gè)新的document
partial update
post /index/type/id/_update
{
"doc": {
"要修改的少數(shù)幾個(gè)field即可,不需要全量的數(shù)據(jù)"
}
}
看起來(lái),好像就比較方便了,每次就傳遞少數(shù)幾個(gè)發(fā)生修改的field即可,不需要將全量的document數(shù)據(jù)發(fā)送過(guò)去
2、圖解partial update實(shí)現(xiàn)原理以及其優(yōu)點(diǎn)

es,其實(shí)是有個(gè)內(nèi)置的腳本支持的,可以基于groovy腳本實(shí)現(xiàn)各種各樣的復(fù)雜操作
基于groovy腳本,如何執(zhí)行partial update
PUT /test_index/test_type/11
{
"num": 0,
"tags": []
}
(1)內(nèi)置腳本
POST /test_index/test_type/11/_update
{
"script" : "ctx._source.num+=1"
}
{
"_index": "test_index",
"_type": "test_type",
"_id": "11",
"_version": 2,
"found": true,
"_source": {
"num": 1,
"tags": []
}
}
(2)外部腳本
//注意,下面一行為腳本內(nèi)容,腳本的存放位置為:

ctx._source.tags+=new_tag
POST /test_index/test_type/11/_update
{
"script": {
"lang": "groovy",
"file": "test-add-tags",
"params": {
"new_tag": "tag1"
}
}
}
(3)用腳本刪除文檔
···
ctx.op = ctx._source.num == count ? 'delete' : 'none'
POST /test_index/test_type/11/_update
{
"script": {
"lang": "groovy",
"file": "test-delete-document",
"params": {
"count": 1
}
}
}
···
(4)upsert操作,如果指定的document不存在,就執(zhí)行upsert中的初始化操作;如果指定的document存在,就執(zhí)行doc或者script指定的partial update操作
···
POST /test_index/test_type/11/_update
{
"script" : "ctx._source.num+=1",
"upsert": {
"num": 0,
"tags": []
}
}
···
mget批量查詢
GET /test_index/_mget
{
"docs":[
{
"_type":"my_test",
"_id":"1"
},
{
"_type":"my_test",
"_id":"2"
}
]
}
//結(jié)果:
{
"docs": [
{
"_index": "test_index",
"_type": "my_test",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"test3": "test3"
}
},
{
"_index": "test_index",
"_type": "my_test",
"_id": "2",
"found": false
}
]
}
如果查詢的document是一個(gè)index下的不同type種的話
···
GET /test_index/_mget
{
"docs":[
{
"_type":"my_test",
"_id":"1"
},
{
"_type":"other_test",
"_id":"1"
}
]
}
//結(jié)果
{
"docs": [
{
"_index": "test_index",
"_type": "my_test",
"_id": "1",
"_version": 2,
"found": true,
"_source": {
"test3": "test3"
}
},
{
"_index": "test_index",
"_type": "other_test",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"name": "li ming",
"age": 12
}
}
]
}
···