2019-06-26

注意點(diǎn):現(xiàn)在kibana/elasticsearch最新版本為7.0,與5.2.0的語(yǔ)法有出入,需要注意

語(yǔ)法,自己查詢

kibana為操作elasticserch的界面,地址可以在啟動(dòng)日志中看到:

image

界面展示:

image

一下為一些操作練習(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é)果如下:

image

定制返回結(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é)果如下:

image

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é)果:

image

document的刪除

  1. DELETE /index/type/id

  2. 不會(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"

}

image

PUT /test_index/my_test/7?version=1

{

"test_str":"test002"

}

image

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

PUT /test_index/my_test/7?version=1

{

"test_str":"test001"

}

image

商機(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)

image

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)容,腳本的存放位置為:

![image](https://upload-images.jianshu.io/upload_images/14757514-fa9602865ee4cd48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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

  }

}

]

}

···

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容