一 Elasticsearch簡介
Elasticsearch 是一個(gè)開源的搜索引擎荐虐,Elasticsearch 使用 Java 編寫的贸伐,它的內(nèi)部使用 Lucene 做索引與搜索症脂,但是它的目的是使全文檢索變得簡單, 通過隱藏 Lucene 的復(fù)雜性,取而代之的提供一套簡單一致的 RESTful API千扔。
- 一個(gè)分布式的實(shí)時(shí)文檔存儲(chǔ),每個(gè)字段 可以被索引與搜索
- 一個(gè)分布式實(shí)時(shí)分析搜索引擎
- 能勝任上百個(gè)服務(wù)節(jié)點(diǎn)的擴(kuò)展库正,并支持 PB 級(jí)別的結(jié)構(gòu)化或者非結(jié)構(gòu)化數(shù)據(jù)
二 安裝并運(yùn)行
已經(jīng)在其他文檔中詳細(xì)介紹曲楚,此次僅做簡單步驟介紹
# 安裝:
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.3-linux-x86_64.tar.gz
$ tar -xzf elasticsearch-7.13.3-linux-x86_64.tar.gz
$ cd elasticsearch-7.13.3/
# 運(yùn)行
sh bin/elasticsearch
# 訪問
$ curl http://192.168.3.14:9200/
{
"name" : "87DNZWU",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "e3A3l85MSZuZlRhxj6IB2w",
"version" : {
"number" : "6.7.0",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "8453f77",
"build_date" : "2019-03-21T15:32:29.844721Z",
"build_snapshot" : false,
"lucene_version" : "7.7.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
三 Query DSL 基本結(jié)構(gòu)
查詢表達(dá)式(Query DSL)是一種非常靈活又富有表現(xiàn)力的查詢語言, Elasticsearch 使用它可以以簡單的 JSON 接口來展現(xiàn) Lucene 功能的絕大部分
// 查詢
GET /_search // 查找整個(gè)ES中所有索引的內(nèi)容
{
"query": {}, //具體的查詢語句對(duì)象
"from": 0, //從第幾條數(shù)據(jù)開始返回
"size": 100, //返回的條數(shù) 默認(rèn)ES最多返回10000條
"highlight": { //高亮
"pre_tags": {}, //高亮內(nèi)容的前面標(biāo)簽 一般都是html比如<b> <p>這種
"post_tags": {},//高亮內(nèi)容的后面標(biāo)簽 一般都是html比如</b> </p>這種
"fields": { //需要高亮的字段
}
},
"sort": [{ //排序
"FIELD": { //排序的字段(需要填上具體的字段名)
"order": "desc"
}
}],
"_source": "{field}" //指定返回的字段
}
// 結(jié)果
{
"took": 350, // 整個(gè)搜索請(qǐng)求消耗了多少毫秒
"timed_out": false, // 表示本次查詢是否超時(shí),如果為true也會(huì)返回結(jié)果,只是數(shù)據(jù)可能不完整
"_shards": { // 顯示查詢中參與的分片信息褥符,成功多少分片失敗多少分片等
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5, // 匹配到的文檔總數(shù)
"max_score": 1, // 為文檔中所有_score的最大值
"hits": [
{
"_index": "mysql-shop_trades-order_item_label_binds",
"_type": "doc",
"_id": "591935",
"_score": 1,
"_source": {
"id": 591935,
"updated_at": "2021-05-20T06:26:09.000Z",
"@version": "1",
"bind_item_label_id": 729,
"label_type": "brand",
"created_at": "2021-05-20T06:26:09.000Z",
"@timestamp": "2021-07-07T07:31:36.262Z",
"is_deleted": 0,
"table_name": "order_item_label_binds",
"bar_code": "6907925004486"
}
}
]
}
}
四 指定索引搜索
上述查詢會(huì)搜索ES中的所有索引龙誊,但通常只需要去固定一個(gè)或幾個(gè)索引中搜索,搜索全部無疑會(huì)造成資源的浪費(fèi)喷楣,在ES中可以通過以下幾種方法來指定索引
- 指定一個(gè)固定的索引趟大,
ops-coffee-nginx-2019.05.15
為索引名字
GET /mysql-shop_trades-order_statics/_search
以上表示在mysql-shop_trades-order_statics
索引下查找數(shù)據(jù)
- 指定多個(gè)固定索引,多個(gè)索引名字用逗號(hào)分割
GET /mysql-shop_trades-order_statics,mysql-shop_trades-order_item_labels/_search
- 用*號(hào)匹配铣焊,在匹配到的所有索引下查找數(shù)據(jù)
GET /mysql-shop_trades-*/_search
這里也可以用逗號(hào)分割多個(gè)匹配索引
五 DSL查詢
1逊朽、篩選字段
// 篩選_source的數(shù)據(jù),單個(gè)字段
GET /_search
{
"_source": "bar_code",
"query": {}
}
// 篩選_source的數(shù)據(jù),多個(gè)字段
{
"_source": {
"includes": ["store_id", "sku_id"]
},
"query": {}
}
// 對(duì)字段進(jìn)行轉(zhuǎn)換
{
"docvalue_fields": [
{
"field": "updated_at",
"format": "yyyy-MM-dd HH:mm:ss"
},
{
"field": "num",
"format": "long" // 沒有作用,懵逼...
}
],
"query": {}
}
2曲伊、多條件查詢 (where)
-
constant_score:裝另一個(gè)查詢的查詢,固定分?jǐn)?shù)查詢叽讳,支持filter查詢,不支持match查詢:
{ "constant_score": { "filter": { "match": { "name": "小米" } }, "boost": 10 } }
bool:主要與其他關(guān)鍵字組合使用坟募,多條件的查詢必須要用bool包在外層绽榛,然后再根據(jù)具體的業(yè)務(wù)來拼接。
{
"query": {
"bool": {
"should": [{}], //滿足其中一個(gè)對(duì)象查詢條件就行 像sql里的or
"must": [{}], //必須滿足所有對(duì)象的查詢條件 就像sql里的and
"must_not": [{}] //必須不滿足所有對(duì)象的查詢條件 就像sql里的and !=
}
}
}
- must: 類似于SQL中的AND婿屹,必須包含
- must_not: 類似于SQL中的NOT灭美,必須不包含
-
should: 滿足這些條件中的任何條件都會(huì)增加評(píng)分
_score
,不滿足也不影響昂利,should
只會(huì)影響查詢結(jié)果的_score
值届腐,并不會(huì)影響結(jié)果的內(nèi)容 -
filter: 與must相似,但不會(huì)對(duì)結(jié)果進(jìn)行相關(guān)性評(píng)分
_score
蜂奸,大多數(shù)情況下我們對(duì)于日志的需求都無相關(guān)性的要求犁苏,所以建議查詢的過程中多用filter
3、group by:
ES本身沒有g(shù)roup關(guān)鍵詞搜索扩所,但支持聚合查詢围详,,需要使用關(guān)鍵字aggs
// 單個(gè)字段 group by
{
"query":{},//這里省略你的查詢條件
"aggs": {
"age_group": {//這個(gè)是指你要返回字段名
"terms": { //這里還可以用其它關(guān)鍵詞 這里terms才能實(shí)現(xiàn)group by效果
"field": "age",//groupby的字段
"size":1 //返回的條數(shù) 相當(dāng)于group by limit
}
}
}
}
// 多字段group by (如 group by sku_id,store_id)
// 方法一:script
{
"query":{},
"aggs": {
"age_group": {
"terms": {
"script":{
"source": """ 's' + doc['store_id'] + '_s' + doc['sku_id'] """,
"lang": "painless"
},
"size": 10
}
}
}
}
// 方法二:copy to
1\. 設(shè)置mapping中的多個(gè)字段,copy_to 為同一個(gè)字段(skuId_storeId)
2\. 搜索新字段
{
"query":{},
"aggs": {
"list": {
"terms": {
"field": "skuId_storeId
"size":1
}
}
}
}
// 方法三:multi_terms (使用高版本助赞,目前6.7不支持)
{
"aggs": {
"genres_and_products": {
"multi_terms": {
"terms": [{
"field": "genre"
}, {
"field": "product"
}]
}
}
}
}
4买羞、order by
order by:注意日期格式和數(shù)值格式才支持排序;文本不支持雹食,如果要排序畜普, 需把字段設(shè)置為not analysis
// 單排序
{
"query": {
"sort": {
"id": "desc"
}
}
}
// avg按照平均值排序
{
"query": {
"sort": [
{
"id": "desc"
},
{
"price": {
"order": "asc",
"mode": "avg"
}
}
]
}
}
5、count(distinct)
{
"query":{},
"aggs": {
"total_sku_id": {
"cardinality":{ "field": "sku_id"}
},
"total_entity_store_id": { // 非數(shù)字類型群叶,無法使用field排序吃挑,可以對(duì)field增加fieldData = true,或者對(duì)field.keyword排序街立,建議使用后者舶衬,高效內(nèi)存消耗低
"cardinality":{ "field": "entity_store_id.keyword"}
}
}
}
6、SUM
{
"query":{},
"aggs": {
"total_pay_num": {
"sum": {"field": "num"}
},
"total_cost_fee": {
"sum": {"field": "cost_fee"}
}
}
}
7赎离、distinct :
select distinct(id) from table
{
"query":{},
"collapse": {
"field": "id" //你需要distinct的字段
},
}
8逛犹、limit
1\. 分頁:
1\. form:從第幾個(gè)開始查詢,最開始是0
2\. size:即limit
3\. 使用size蟹瘾,size最大可獲取數(shù)量是xx個(gè)
2\. 獲取所有數(shù)據(jù)的三種方式
1\. scroll深度滾動(dòng)需要根據(jù)scroll_id和循環(huán)取圾浅,取完后,需刪除scroll憾朴,減小內(nèi)存開銷(深度滾動(dòng)高效狸捕,用于處理大量數(shù)據(jù),不適合實(shí)時(shí)獲戎诶住)
2.調(diào)整索引index.max_result_window的大小灸拍,默認(rèn)10000 (大小與堆內(nèi)存成正比,這個(gè)限制內(nèi)存)
3.search_after:請(qǐng)求需增加前一個(gè)結(jié)果的排序砾省,(實(shí)時(shí)游標(biāo)鸡岗,可根據(jù)索引更新和刪除而改變 )
4。 如果是group by查詢獲取所有數(shù)據(jù)编兄, 獲取需要使用到cardinality查詢預(yù)估總數(shù)轩性,再使用partition、num_partitions分區(qū)依次獲取數(shù)據(jù)
9狠鸳、搜索關(guān)鍵字
match:自定字段揣苏,根據(jù)字段關(guān)鍵字進(jìn)行搜索,會(huì)分割關(guān)鍵詞,匹配到含有一個(gè)多多個(gè)詞的匹配
query_string:全文搜索
match_phrase:不分割關(guān)鍵詞 {"match_phrase": {"name":"嬰幼兒奶粉"}}
-
term: 類似SQL where field = x件舵,主要用于數(shù)字匹配卸察;如果要匹配文本,會(huì)自動(dòng)分詞铅祸,不能精準(zhǔn)查詢坑质,需把字段設(shè)置成not analysis
{ "query": { "term": {"bind_item_label_id": 729} } }
-
terms: 類似SQL where field in (x,x),主要用于數(shù)字匹配,
{ "query": { "terms": {"bind_item_label_id": [703,729]} } }
range:: 查詢價(jià)格在1000-2000的商品
{
"query": {
"range": {
"price": {
"gte": 1000,
"lte": 2000
}
}
}
}
- filter:判斷文檔是否滿足條件
{
"query": {
"bool": {
"filter": {
"term": {
"price": 1999
}
}
}
}
}
Elasticsearch:Aggregation
- metric:度量聚合,主要針對(duì)number類型的數(shù)據(jù)涡扼,需要es做較多的計(jì)算工作(類似SQL的SUM稼跳、MAX、AVG壳澳、MIN岂贩、Cardinality茫经、stats<屬于多值分析>等)
- bucket:桶聚合巷波,劃分不同步的桶,將數(shù)據(jù)分配到不同的桶卸伞,(類似SQL中的group by)
- Pipeline Aggregation:管道分析類型抹镊,對(duì)其他聚合結(jié)果進(jìn)行二次聚合
- Matrix Aggregation:矩陣分析類型,支持對(duì)多個(gè)字段的操作并提供一個(gè)結(jié)果矩陣
term aggregation
- size 可以通過size返回top size的文檔荤傲,該術(shù)語聚合針對(duì)頂層術(shù)語(不包含嵌套詞根)垮耳,其搜索過程是將請(qǐng)求向所有分點(diǎn)發(fā)送請(qǐng)求,每個(gè)分片節(jié)點(diǎn)返回size條數(shù)據(jù)遂黍,然后聚合所有分片的結(jié)果(會(huì)對(duì)各分片返回的同樣詞根的數(shù)數(shù)值進(jìn)行相加)终佛,最終從中挑選size條記錄返回給客戶端。從這個(gè)過程也可以看出雾家,其結(jié)果并不是準(zhǔn)確的铃彰,而是一個(gè)近似值。
- Shard Size 為了提高該聚合的精確度芯咧,可以通過shard_size參數(shù)設(shè)置協(xié)調(diào)節(jié)點(diǎn)向各個(gè)分片請(qǐng)求的詞根個(gè)數(shù)牙捉,然后在協(xié)調(diào)節(jié)點(diǎn)進(jìn)行聚合,最后只返回size個(gè)詞根給到客戶端敬飒,shard_size >= size邪铲,如果shard_size設(shè)置小于size,ES會(huì)自動(dòng)將其設(shè)置為size无拗,默認(rèn)情況下shard_size建議設(shè)置為(1.5 * size + 10)带到。
// 單個(gè)字段 group by
{
"query":{},//這里省略你的查詢條件
"aggs": {
"age_group": {//這個(gè)是指你要返回字段名
"terms": { //這里還可以用其它關(guān)鍵詞 這里terms才能實(shí)現(xiàn)group by效果
"field": "age",//groupby的字段
"size":1 //返回的條數(shù) 相當(dāng)于group by limit
}
}
}
}
// 返回結(jié)果格式
{
...
"aggregations" : {
"list" : {
"doc_count_error_upper_bound" : 0, // 該值表示未進(jìn)入最終術(shù)語列表的術(shù)語的最大潛在文檔計(jì)數(shù)
"sum_other_doc_count" : 90 // 該值表示未進(jìn)入最終術(shù)語列表的術(shù)語的最大潛在文檔計(jì)數(shù)
"buckets" : [ // 返回doc_count排名最前的10個(gè),受size參數(shù)的影響
{
"key" : "1",
"doc_count" : 24,
"total_refund_fee" : {
"value" : 0.0
},
"total_cost_fee" : {
"value" : -14976.0
},
}
]
}
}
}
}
match_phrase :查詢分析文本英染,創(chuàng)建詞組查詢
舉例子
GET mysql-shop_trades-order_item_label_binds/_search/?scroll=1m
{
"docvalue_fields": [
{
"field": "updated_at",
"format": "yyyy-MM-dd HH:mm:ss"
}
],
"size": 1000,
"sort": {"id":"desc"},
"query": {
"bool": {
"must": [
{"match": {"is_deleted": 0}},
{"match": {"label_type": "brand"}},
{
"constant_score": {
"filter": {
"terms": {
"bind_item_label_id": [703, 2, 729]
}
}
}
}
]
}
}
}
GET mysql-shop_trades-order_item_label_binds/_search/?scroll=1m
{
"_source": "bar_code",
"query": {
"bool": {
"filter": [
{"match": {"is_deleted": 0}},
{"match_phrase": {"label_type": "brand"}},
{"terms": {"bind_item_label_id": [703, 2, 729]}}
]
}
},
"aggs": {
"bar_code_group": {
"terms": {
"field": "bar_code.keyword",
"size": 10
}
}
}
}
GET mysql-shop_trades-order_item_label_binds,mysql-shop_trades-order_statics/_search
{
"query": {
"bool": {
"filter": [
{"match_phrase": {"sys_name": "yiqigou"}},
{"range": {"num": {"lte": 2000}}},
{"range": {"return_num": {"gte": -1000}}},
{"range": {"total_price": {"lte": 1000000}}},
{"match": {"id": 60}},
{"term": {"order_type": 0}},
{"term": {"item_type": 0}},
{"range": {"date": {
"gte": "2020-01-21 00:00:00",
"lte": "2021-07-22 00:00:00",
"format": "yyyy-MM-dd HH:mm:ss",
"time_zone": "+08:00"
}}}
],
"must_not": [
{"terms": {"store_id": [165]}}
]
}
}
}
設(shè)置fieldData
// 第一步揽惹,創(chuàng)建索引 (如果已經(jīng)有索引,直接看第二步)
PUT mysql-shop_trades-order_statics2
{
"mappings": {
"_doc": {
"properties": {
"entity_store_id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
}
// 第二步 設(shè)置fieldData為true
PUT mysql-shop_trades-order_statics/_mapping/_doc
{
"properties": {
"entity_store_id": {
"type": "text",
"fielddata": true
}
}
}
// 第三步 可以查看該索引的Mapping結(jié)構(gòu),fieldData是否加上去
{
"mapping": {
"doc": {
"properties": {
"entity_store_id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
},
"fielddata": true
}
}
}
}
}
延伸
設(shè)置 max_result_window
PUT /mysql-shop_trades-order_statics/_settings
{
"index": {
"max_result_window": 100000
}
}
測試鏈接
[ci123dev@ts_web_123 ~]$ curl -H "Content-Type:application/json" _GET -u geekman 'http://192.168.1.123:9227/_search' -d '{ "size" : 1, "query" : { "term" : { "store_id" : { "value" : 165 } } } }'
Enter host password for user 'geekman':
{"took":5745,"timed_out":false,"_shards":{"total":46,"successful":46,"skipped":0,"failed":0},"hits":{"total":{"value":1213,"relation":"eq"},"max_score":1.0,"hits":[{"_index":"mysql-shop_trades-order_statics","_type":"_doc","_id":"1118612","_score":1.0,"_source":{"@version":"1","order_type":0,"brand_store_id":-1,"num":1,"created_at":"2021-01-11T08:51:16.000Z","refund_order_profit":0,"sys_name":"yiqigou","brand_id":0,"trade_id":6601283,"cashier_account_id":"331c91ee9a574524ba11b0e9db701854","sales_type":"sale","return_cost_fee":0,"guider_account_id":"","bar_code":"6930955714926","sku_id":4369714,"personal_guider_id":0,"order_profit":3.00,"@timestamp":"2021-07-18T07:11:27.171Z","order_id":7895389,"date":"2021-01-10T16:00:00.000Z","trade_from":"cashier","target_order_id":0,"refund_fee":0,"vuid":"223903004","updated_at":"2021-01-11T08:51:16.000Z","dealer_code":"","table_name":"order_statics","item_type":0,"trade_unique_id":"2101111651158000","store_id":165,"entity_store_id":"201611181428483942","total_price":18.00,"cost_fee":15.00,"pay_fee":18.00,"return_num":0,"item_id":5709045,"id":1118612}}]}}