<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          別只會(huì)搜日志了,求你懂點(diǎn)原理吧

          共 20345字,需瀏覽 41分鐘

           ·

          2020-10-16 20:24

          作者 | 悟空聊架構(gòu)

          來源 |?悟空聊架構(gòu)(ID:PassJava666)

          轉(zhuǎn)載請聯(lián)系授權(quán)(微信ID:PassJava)

          本篇主要內(nèi)容如下:

          主要內(nèi)容

          前言

          項(xiàng)目中我們總是用?Kibana?界面來搜索測試或生產(chǎn)環(huán)境下的日志,來看下有沒有異常信息。Kibana?就是我們常說的?ELK?中的?K

          Kibana 界面如下圖所示:

          Kibana 界面

          但這些日志檢索原理是什么呢?這里就該我們的 Elasticsearch 搜索引擎登場了。

          我會(huì)分為三篇來講解 Elasticsearch(簡稱ES)的原理、實(shí)戰(zhàn)及部署。本篇是講解 ES 的上篇。

          • 上篇:?講解 ES 的原理、中文分詞的配置。
          • 中篇:?實(shí)戰(zhàn) ES 應(yīng)用。
          • 下篇:?ES 的集群部署。

          為什么要分成三篇,因?yàn)槊恳黄己荛L,而且側(cè)重點(diǎn)不一樣,所以分成三篇來講解。

          一、Elasticsearch 簡介

          1.1 什么是 Elasticsearch?

          Elasticsearch 是一個(gè)分布式的開源搜索和分析引擎,適用于所有類型的數(shù)據(jù),包括文本、數(shù)字、地理空間、結(jié)構(gòu)化和非結(jié)構(gòu)化數(shù)據(jù)。簡單來說只要涉及搜索和分析相關(guān)的, ES 都可以做。

          1.2 Elasticsearch 的用途?

          Elasticsearch 在速度和可擴(kuò)展性方面都表現(xiàn)出色,而且還能夠索引多種類型的內(nèi)容,這意味著其可用于多種用例:

          • 比如一個(gè)在線網(wǎng)上商店,您可以在其中允許客戶搜索您出售的產(chǎn)品。在這種情況下,您可以使用 Elasticsearch 存儲(chǔ)整個(gè)產(chǎn)品目錄和庫存,并為它們提供搜索和自動(dòng)完成建議。
          搜索手機(jī)
          • 比如收集日志或交易數(shù)據(jù),并且要分析和挖掘此數(shù)據(jù)以查找趨勢,統(tǒng)計(jì)信息,摘要或異常。在這種情況下,您可以使用 Logstash(Elasticsearch / Logstash / Kibana 堆棧的一部分)來收集,聚合和解析數(shù)據(jù),然后讓Logstash將這些數(shù)據(jù)提供給 Elasticsearch。數(shù)據(jù)放入 Elasticsearch 后,您可以運(yùn)行搜索和聚合以挖掘您感興趣的任何信息。

          1.3 Elasticsearch 的工作原理?

          ELK 原理圖

          Elasticsearch 是在 Lucene 基礎(chǔ)上構(gòu)建而成的。ES 在 Lucence 上做了很多增強(qiáng)。

          Lucene 是apache軟件基金會(huì) 4 的 jakarta 項(xiàng)目組的一個(gè)子項(xiàng)目,是一個(gè)開放源代碼的全文檢索引擎工具包,但它不是一個(gè)完整的全文檢索引擎,而是一個(gè)全文檢索引擎的架構(gòu),提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟件開發(fā)人員提供一個(gè)簡單易用的工具包,以方便的在目標(biāo)系統(tǒng)中實(shí)現(xiàn)全文檢索的功能,或者是以此為基礎(chǔ)建立起完整的全文檢索引擎。(來自百度百科)

          Elasticsearch 的原始數(shù)據(jù)從哪里來?

          原始數(shù)據(jù)從多個(gè)來源 ( 包括日志、系統(tǒng)指標(biāo)和網(wǎng)絡(luò)應(yīng)用程序 ) 輸入到 Elasticsearch 中。

          Elasticsearch 的數(shù)據(jù)是怎么采集的?

          數(shù)據(jù)采集指在 Elasticsearch 中進(jìn)行索引之前解析、標(biāo)準(zhǔn)化并充實(shí)這些原始數(shù)據(jù)的過程。這些數(shù)據(jù)在 Elasticsearch 中索引完成之后,用戶便可針對他們的數(shù)據(jù)運(yùn)行復(fù)雜的查詢,并使用聚合來檢索自身數(shù)據(jù)的復(fù)雜匯總。這里用到了 Logstash,后面會(huì)介紹。

          怎么可視化查看想要檢索的數(shù)據(jù)?

          這里就要用到 Kibana 了,用戶可以基于自己的數(shù)據(jù)進(jìn)行搜索、查看數(shù)據(jù)視圖等。

          1.4 Elasticsearch 索引是什么?

          Elasticsearch 索引指相互關(guān)聯(lián)的文檔集合。Elasticsearch 會(huì)以 JSON 文檔的形式存儲(chǔ)數(shù)據(jù)。每個(gè)文檔都會(huì)在一組鍵 ( 字段或?qū)傩缘拿Q ) 和它們對應(yīng)的值 ( 字符串、數(shù)字、布爾值、日期、數(shù)值組、地理位置或其他類型的數(shù)據(jù) ) 之間建立聯(lián)系。

          Elasticsearch 使用的是一種名為倒排索引的數(shù)據(jù)結(jié)構(gòu),這一結(jié)構(gòu)的設(shè)計(jì)可以允許十分快速地進(jìn)行全文本搜索。倒排索引會(huì)列出在所有文檔中出現(xiàn)的每個(gè)特有詞匯,并且可以找到包含每個(gè)詞匯的全部文檔。

          在索引過程中,Elasticsearch 會(huì)存儲(chǔ)文檔并構(gòu)建倒排索引,這樣用戶便可以近實(shí)時(shí)地對文檔數(shù)據(jù)進(jìn)行搜索。索引過程是在索引 API 中啟動(dòng)的,通過此 API 您既可向特定索引中添加 JSON 文檔,也可更改特定索引中的 JSON 文檔。

          1.5 Logstash 的用途是什么?

          Logstash 就是?ELK?中的?L。

          Logstash 是 Elastic Stack 的核心產(chǎn)品之一,可用來對數(shù)據(jù)進(jìn)行聚合和處理,并將數(shù)據(jù)發(fā)送到 Elasticsearch。Logstash 是一個(gè)開源的服務(wù)器端數(shù)據(jù)處理管道,允許您在將數(shù)據(jù)索引到 Elasticsearch 之前同時(shí)從多個(gè)來源采集數(shù)據(jù),并對數(shù)據(jù)進(jìn)行充實(shí)和轉(zhuǎn)換。

          1.6 Kibana 的用途是什么?

          Kibana 是一款適用于 Elasticsearch 的數(shù)據(jù)可視化和管理工具,可以提供實(shí)時(shí)的直方圖、線性圖等。

          1.7 為什么使用 Elasticsearch

          • ES 很快,近實(shí)時(shí)的搜索平臺(tái)。
          • ES 具有分布式的本質(zhì)特質(zhì)。
          • ES 包含一系列廣泛的功能,比如數(shù)據(jù)匯總和索引生命周期管理。

          官方文檔:https://www.elastic.co/cn/what-is/elasticsearch

          二、ES 基本概念

          2.1 Index ( 索引 )

          動(dòng)詞:相當(dāng)于 Mysql 中的 insert

          名詞:相當(dāng)于 Mysql 中的 database

          與 mysql 的對比

          序號MysqlElasticsearch
          1Mysql 服務(wù)ES 集群服務(wù)
          2數(shù)據(jù)庫 Database索引 Index
          3表 Table類型 Type
          4記錄 Records ( 一行行記錄 )文檔 Document ( JSON 格式 )

          2.2 倒排索引

          假如數(shù)據(jù)庫有如下電影記錄:

          1-大話西游

          2-大話西游外傳

          3-解析大話西游

          4-西游降魔外傳

          5-夢幻西游獨(dú)家解析

          分詞:將整句分拆為單詞

          序號保存到 ES 的詞對應(yīng)的電影記錄序號
          A西游1,2, 3,4, 5
          B大話1,2, 3
          C外傳2,4, 5
          D解析3,5
          E降魔4
          F夢幻5
          G獨(dú)家5

          檢索:獨(dú)家大話西游

          將?獨(dú)家大話西游?解析拆分成?獨(dú)家大話、西游

          ES 中 A、B、G 記錄 都有這三個(gè)詞的其中一種, ?所以 1,2, 3,4, 5 號記錄都有相關(guān)的詞被命中。

          1 號記錄命中 2 次, A、B 中都有 ( 命中?2?次 ) ,而且 1 號記錄有?2?個(gè)詞,相關(guān)性得分:2?次/2?個(gè)詞=1

          2 號記錄命中 2 個(gè)詞 A、B 中的都有 ( 命中?2?次 ) ,而且 2 號記錄有?2?個(gè)詞,相關(guān)性得分:2?次/3?個(gè)詞=?0.67

          3 號記錄命中 2 個(gè)詞 A、B 中的都有 ( 命中?2?次 ) ,而且 3 號記錄有?2?個(gè)詞,相關(guān)性得分:2?次/3?個(gè)詞=?0.67

          4 號記錄命中 2 個(gè)詞 A 中有 ( 命中?1?次 ) ,而且 4 號記錄有?2?個(gè)詞,相關(guān)性得分:1?次/3?個(gè)詞=?0.33

          5 號記錄命中 2 個(gè)詞 A 中有 ( 命中?2?次 ) ,而且 4 號記錄有?4?個(gè)詞,相關(guān)性得分:2?次/4?個(gè)詞=?0.5

          所以檢索出來的記錄順序如下:

          1-大話西游 ( 想關(guān)性得分:1 )

          2-大話西游外傳 ( 想關(guān)性得分:0.67 )

          3-解析大話西游 ( 想關(guān)性得分:0.67 )

          5-夢幻西游獨(dú)家解析 ( 想關(guān)性得分:0.5 )

          4-西游降魔 ( 想關(guān)性得分:0.33 )

          三、Docker 搭建環(huán)境

          3.1. 搭建 Elasticsearch 環(huán)境

          搭建虛擬機(jī)環(huán)境和安裝 docker 可以參照之前寫的文檔:

          下面我們來講下如何搭建 ES 環(huán)境。

          1 ) 下載鏡像文件

          docker?pull?elasticsearch:7.4.2

          2 ) 創(chuàng)建實(shí)例

          • 1. 映射配置文件
          配置映射文件夾
          mkdir?-p?/mydata/elasticsearch/config

          配置映射文件夾
          mkdir?-p?/mydata/elasticsearch/data

          設(shè)置文件夾權(quán)限任何用戶可讀可寫
          chmod?777?/mydata/elasticsearch?-R

          配置?http.host
          echo?"http.host:?0.0.0.0"?>>?/mydata/elasticsearch/config/elasticsearch.yml
          • 2. 啟動(dòng) elasticsearch 容器
          docker?run?--name?elasticsearch?-p?9200:9200?-p?9300:9300?\
          -e?"discovery.type"="single-node"?\
          -e?ES_JAVA_OPTS="-Xms64m?-Xmx128m"?\
          -v?/mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml?\
          -v?/mydata/elasticsearch/data:/usr/share/elasticsearch/data?\
          -v?/mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins?\
          -d?elasticsearch:7.4.2
          • 3. 訪問 elasticsearch 服務(wù)

          訪問:http://192.168.56.10:9200

          返回的 reponse

          {
          ??"name"?:?"8448ec5f3312",
          ??"cluster_name"?:?"elasticsearch",
          ??"cluster_uuid"?:?"xC72O3nKSjWavYZ-EPt9Gw",
          ??"version"?:?{
          ????"number"?:?"7.4.2",
          ????"build_flavor"?:?"default",
          ????"build_type"?:?"docker",
          ????"build_hash"?:?"2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
          ????"build_date"?:?"2019-10-28T20:40:44.881551Z",
          ????"build_snapshot"?:?false,
          ????"lucene_version"?:?"8.2.0",
          ????"minimum_wire_compatibility_version"?:?"6.8.0",
          ????"minimum_index_compatibility_version"?:?"6.0.0-beta1"
          ??},
          ??"tagline"?:?"You?Know,?for?Search"
          }

          訪問:http://192.168.56.10:9200/_cat 訪問節(jié)點(diǎn)信息

          127.0.0.1?62?90?0?0.06?0.10?0.05?dilm?*?8448ec5f3312

          3.2. 搭建 Kibana 環(huán)境

          docker?pull?kibana:7.4.2

          docker?run?--name?kibana?-e?ELASTICSEARCH_HOSTS=http://192.168.56.10:9200?-p?5601:5601?-d?kibana:7.4.2

          訪問 kibana: http://192.168.56.10:5601/

          kibana

          四、初階檢索玩法

          4.1._cat 用法

          GET?/_cat/nodes:?查看所有節(jié)點(diǎn)
          GET?/_cat/health:?查看?es?健康狀況
          GET?/_cat/master:?查看主節(jié)點(diǎn)
          GET?/_cat/indices:?查看所有索引

          查詢匯總:
          /_cat/allocation
          /_cat/shards
          /_cat/shards/{index}
          /_cat/master
          /_cat/nodes
          /_cat/tasks
          /_cat/indices
          /_cat/indices/{index}
          /_cat/segments
          /_cat/segments/{index}
          /_cat/count
          /_cat/count/{index}
          /_cat/recovery
          /_cat/recovery/{index}
          /_cat/health
          /_cat/pending_tasks
          /_cat/aliases
          /_cat/aliases/{alias}
          /_cat/thread_pool
          /_cat/thread_pool/{thread_pools}
          /_cat/plugins
          /_cat/fielddata
          /_cat/fielddata/{fields}
          /_cat/nodeattrs
          /_cat/repositories
          /_cat/snapshots/{repository}
          /_cat/templates

          4.2. 索引一個(gè)文檔 ( 保存 )

          例子:在?customer?索引下的?external?類型下保存標(biāo)識為?1?的數(shù)據(jù)。

          • 使用 Kibana 的 Dev Tools 來創(chuàng)建
          PUT?member/external/1

          {
          "name":"jay?huang"
          }

          Reponse:

          {
          ????"_index":?"member",?//在哪個(gè)索引
          ????"_type":?"external",//在那個(gè)類型
          ????"_id":?"2",//記錄?id
          ????"_version":?7,//版本號
          ????"result":?"updated",//操作類型
          ????"_shards":?{
          ????????"total":?2,
          ????????"successful":?1,
          ????????"failed":?0
          ????},
          ????"_seq_no":?9,
          ????"_primary_term":?1
          }
          • 也可以通過 Postman 工具發(fā)送請求來創(chuàng)建記錄。
          創(chuàng)建一條記錄

          注意:

          PUT 和 POST 都可以創(chuàng)建記錄。

          POST:如果不指定 id,自動(dòng)生成 id。如果指定 id,則修改這條記錄,并新增版本號。

          PUT:必須指定 id,如果沒有這條記錄,則新增,如果有,則更新。

          4.3 查詢文檔

          請求:http://192.168.56.10:9200/member/external/2

          Reposne:
          {
          ????"_index":?"member",???//在哪個(gè)索引
          ????"_type":?"external",??//在那個(gè)類型
          ????"_id":?"2",???????????//記錄?id
          ????"_version":?7,????????//版本號
          ????"_seq_no":?9,?????????//并發(fā)控制字段,每次更新就會(huì)+1,用來做樂觀鎖
          ????"_primary_term":?1,???//同上,主分片重新分配,如重啟,就會(huì)變化
          ????"found":?true,
          ????"_source":?{?//真正的內(nèi)容
          ????????"name":?"jay?huang"
          ?}
          }

          _seq_no 用作樂觀鎖

          每次更新完數(shù)據(jù)后,_seq_no 就會(huì)+1,所以可以用作并發(fā)控制。

          當(dāng)更新記錄時(shí),如果_seq_no 與預(yù)設(shè)的值不一致,則表示記錄已經(jīng)被至少更新了一次,不允許本次更新。

          用法如下:

          請求更新記錄?2:?http://192.168.56.10:9200/member/external/2?if_seq_no=9&&if_primary_term=1
          返回結(jié)果:
          {
          ????"_index":?"member",
          ????"_type":?"external",
          ????"_id":?"2",
          ????"_version":?9,
          ????"result":?"updated",
          ????"_shards":?{
          ????????"total":?2,
          ????????"successful":?1,
          ????????"failed":?0
          ????},
          ????"_seq_no":?11,
          ????"_primary_term":?1
          }

          _seq_no 等于 10,且_primary_term=1 時(shí)更新數(shù)據(jù),執(zhí)行一次請求后,再執(zhí)行上面的請求則會(huì)報(bào)錯(cuò):版本沖突

          {
          ????"error":?{
          ????????"root_cause":?[
          ?{
          ????????????????"type":?"version_conflict_engine_exception",
          ????????????????"reason":?"[2]:?version?conflict,?required?seqNo?[10],?primary?term?[1].?current?document?has?seqNo?[11]?and?primary?term?[1]",
          ????????????????"index_uuid":?"CX6uwPBKRByWpuym9rMuxQ",
          ????????????????"shard":?"0",
          ????????????????"index":?"member"
          ?}
          ????????],
          ????????"type":?"version_conflict_engine_exception",
          ????????"reason":?"[2]:?version?conflict,?required?seqNo?[10],?primary?term?[1].?current?document?has?seqNo?[11]?and?primary?term?[1]",
          ????????"index_uuid":?"CX6uwPBKRByWpuym9rMuxQ",
          ????????"shard":?"0",
          ????????"index":?"member"
          ????},
          ????"status":?409
          }

          4.4 更新文檔

          • 用法

          POST 帶?_update?的更新操作,如果原數(shù)據(jù)沒有變化,則 repsonse 中的 result 返回 noop ( 沒有任何操作 ) ,version 也不會(huì)變化。

          請求體中需要用?doc?將請求數(shù)據(jù)包裝起來。

          POST 請求:http://192.168.56.10:9200/member/external/2/_update
          {
          ????"doc":{
          ????????"name":"jay?huang"
          ?}
          }
          響應(yīng):
          {
          ????"_index":?"member",
          ????"_type":?"external",
          ????"_id":?"2",
          ????"_version":?12,
          ????"result":?"noop",
          ????"_shards":?{
          ????????"total":?0,
          ????????"successful":?0,
          ????????"failed":?0
          ????},
          ????"_seq_no":?14,
          ????"_primary_term":?1
          }

          使用場景:對于大并發(fā)更新,建議不帶?_update。對于大并發(fā)查詢,少量更新的場景,可以帶_update,進(jìn)行對比更新。

          • 更新時(shí)增加屬性

          請求體中增加?age?屬性

          http://192.168.56.10:9200/member/external/2/_update
          request:
          {
          ????"doc":{
          ????????"name":"jay?huang",
          ????????"age":?18
          ?}
          }
          response:
          {
          ????"_index":?"member",
          ????"_type":?"external",
          ????"_id":?"2",
          ????"_version":?13,
          ????"result":?"updated",
          ????"_shards":?{
          ????????"total":?2,
          ????????"successful":?1,
          ????????"failed":?0
          ????},
          ????"_seq_no":?15,
          ????"_primary_term":?1
          }

          4.5 刪除文檔和索引

          • 刪除文檔
          DELETE 請求:http://192.168.56.10:9200/member/external/2
          response:
          {
          ????"_index":?"member",
          ????"_type":?"external",
          ????"_id":?"2",
          ????"_version":?2,
          ????"result":?"deleted",
          ????"_shards":?{
          ????????"total":?2,
          ????????"successful":?1,
          ????????"failed":?0
          ????},
          ????"_seq_no":?1,
          ????"_primary_term":?1
          }
          • 刪除索引
          DELETE 請求:http://192.168.56.10:9200/member
          repsonse:
          {
          ????"acknowledged":?true
          }
          • 沒有刪除類型的功能

          4.6 批量導(dǎo)入數(shù)據(jù)

          使用 kinaba 的 dev tools 工具,輸入以下語句

          POST?/member/external/_bulk
          {"index":{"_id":"1"}}
          {"name":"Jay?Huang"}
          {"index":{"_id":"2"}}
          {"name":"Jackson?Huang"}

          執(zhí)行結(jié)果如下圖所示:

          批量插入數(shù)據(jù)
          • 拷貝官方樣本數(shù)據(jù)
          https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json
          官方樣本數(shù)據(jù)
          • 在 kibana 中執(zhí)行腳本
          POST?/bank/account/_bulk
          {"index":{"_id":"1"}}
          {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880?Holmes?Lane","employer":"Pyrami","email":"[email protected]","city":"Brogan","state":"IL"}
          {"index":{"_id":"6"}}
          ......
          批量插入樣本數(shù)據(jù)的執(zhí)行結(jié)果
          • 查看所有索引
          查看所有索引

          可以從返回結(jié)果中看到 bank 索引有 1000 條數(shù)據(jù),占用了 440.2kb 存儲(chǔ)空間。

          五、高階檢索玩法

          5.1 兩種查詢方式

          5.1.1 ?URL 后接參數(shù)

          GET?bank/_search?q=*&sort=account_number:?asc

          ```/_search?q=*&sort=account_number: asc`

          查詢出所有數(shù)據(jù),共 1000 條數(shù)據(jù),耗時(shí) 1ms,只展示 10 條數(shù)據(jù) ( ES 分頁 )

          URL 后接參數(shù)

          屬性值說明:

          took?–?ES?執(zhí)行搜索的時(shí)間?(?毫秒?)
          timed_out?–?ES?是否超時(shí)
          _shards?–?有多少個(gè)分片被搜索了,以及統(tǒng)計(jì)了成功/失敗/跳過的搜索的分片
          max_score?–?最高得分
          hits.total.value?-?命中多少條記錄
          hits.sort?-?結(jié)果的排序?key?鍵,沒有則按?score?排序
          hits._score?-?相關(guān)性得分
          參考文檔:
          https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html

          5.1.2 URL 加請求體進(jìn)行檢索 ( QueryDSL )

          請求體中寫查詢條件

          語法:

          GET?bank/_search
          {
          ??"query":{"match_all":?{}},
          ??"sort":?[
          ????{"account_number":?"asc"?}
          ?]
          }

          示例:查詢出所有,先按照 accout_number 升序排序,再按照 balance 降序排序

          URL 加請求體進(jìn)行檢索

          5.2 詳解 QueryDSL 查詢

          DSL: Domain Specific Language

          5.2.1 全部匹配 match_all

          示例:查詢所有記錄,按照 balance 降序排序,只返回第 11 條記錄到第 20 條記錄,只顯示 balance 和 firstname 字段。

          GET?bank/_search
          {
          ??"query":?{
          ????"match_all":?{}
          ??},
          ??"sort":?[
          ?{
          ??????"balance":?{
          ????????"order":?"desc"
          ?}
          ?}
          ??],
          ??"from":?10,
          ??"size":?10,
          ??"_source":?["balance",?"firstname"]
          }

          5.2.2 匹配查詢 match

          • 基本類型 ( 非字符串 ) ,精確匹配
          GET?bank/_search
          {
          ??"query":?{
          ????"match":?{"account_number":?"30"}
          ?}
          }
          • 字符串,全文檢索
          GET?bank/_search
          {
          ??"query":?{
          ????"match":?{
          ??????"address":?"mill?road"
          ?}
          ?}
          }
          字符串全文檢索

          全文檢索按照評分進(jìn)行排序,會(huì)對檢索條件進(jìn)行分詞匹配。

          查詢?address?中包含?mill?或者?road?或者?mill road?的所有記錄,并給出相關(guān)性得分。

          查到了 32 條記錄,最高的一條記錄是 Address = "990 Mill Road",得分:8.926605. Address="198 Mill Lane" 評分 5.4032025,只匹配到了 Mill 單詞。

          5.2.3 短語匹配 match_phase

          將需要匹配的值當(dāng)成一個(gè)整體單詞 ( 不分詞 ) 進(jìn)行檢索

          GET?bank/_search
          {
          ??"query":?{
          ????"match_phrase":?{
          ??????"address":?"mill?road"
          ?}
          ?}
          }

          查出 address 中包含?mill road?的所有記錄,并給出相關(guān)性得分

          5.2.4 多字段匹配 multi_match

          GET?bank/_search
          {
          ??"query":?{
          ????"multi_match":?{
          ??????"query":?"mill?land",
          ??????"fields":?[
          ????????"state",
          ????????"address"
          ?]
          ?}
          ?}
          }

          multi_match 中的 query 也會(huì)進(jìn)行分詞。

          查詢?state?包含?mill?或?land?或者?address?包含?mill?或?land?的記錄。

          5.2.5 復(fù)合查詢 bool

          復(fù)合語句可以合并任何其他查詢語句,包括復(fù)合語句。復(fù)合語句之間可以相互嵌套,可以表達(dá)復(fù)雜的邏輯。

          搭配使用 must,must_not,should

          must: 必須達(dá)到 must 指定的條件。( 影響相關(guān)性得分 )

          must_not: 必須不滿足 must_not 的條件。( 不影響相關(guān)性得分 )

          should: 如果滿足 should 條件,則可以提高得分。如果不滿足,也可以查詢出記錄。( 影響相關(guān)性得分 )

          示例:查詢出地址包含 mill,且性別為 M,年齡不等于 28 的記錄,且優(yōu)先展示 firstname 包含 Winnie 的記錄。

          GET?bank/_search
          {
          ??"query":?{
          ????"bool":?{
          ??????"must":?[
          ? {
          ??????????"match":?{
          ????????????"address":?"mill"
          ? }
          ???????},
          ? {
          ??????????"match":?{
          ????????????"gender":?"M"
          ? }
          ? }
          ?????],
          ??????"must_not":?[
          ? {
          ??????????"match":?{
          ????????????"age":?"28"
          ? }
          ?}],
          ??????"should":?[
          ? {
          ??????????"match":?{
          ????????????"firstname":?"Winnie"
          ? }
          ? }]
          ? }
          ?}
          }

          5.2.6 filter 過濾

          不影響相關(guān)性得分,查詢出滿足 filter 條件的記錄。

          在 bool 中使用。

          GET?bank/_search
          {
          ??"query":?{
          ????"bool":?{
          ??????"filter":?[
          ? {
          ??????????"range":?{
          ????????????"age":?{
          ??????????????"gte":18,
          ??????????????"lte":40
          ? }
          ?}
          ? }]
          ? }
          ?}
          }

          5.2.7 term 查詢

          匹配某個(gè)屬性的值。

          全文檢索字段用 match,其他非 text 字段匹配用 term

          keyword:文本精確匹配 ( 全部匹配 )

          match_phase:文本短語匹配

          非?text?字段精確匹配
          GET?bank/_search
          {
          ??"query":?{
          ????"term":?{
          ??????"age":?"20"
          ? }
          ? }
          }

          5.2.8 aggregations 聚合

          聚合:從數(shù)據(jù)中分組和提取數(shù)據(jù)。類似于 SQL GROUP BY 和 SQL 聚合函數(shù)。

          Elasticsearch 可以將命中結(jié)果和多個(gè)聚合結(jié)果同時(shí)返回。

          聚合語法:

          "aggregations"?:?{
          ????"<聚合名稱?1>"?:?{
          ????????"<聚合類型>"?:?{
          ????????????<聚合體內(nèi)容>
          ? }
          ????????[,"元數(shù)據(jù)"?:?{??[]?}]?
          ????????[,"aggregations"?:?{?[]+?}]?
          ? }
          ????["聚合名稱?2>"?:?{?...?}]*
          }
          • 示例 1:搜索 address 中包含 big 的所有人的年齡分布 ( 前 10 條 ) 以及平均年齡,以及平均薪資
          GET?bank/_search
          {
          ??"query":?{
          ????"match":?{
          ??????"address":?"mill"
          ?}
          ??},
          ??"aggs":?{
          ????"ageAggr":?{
          ??????"terms":?{
          ????????"field":?"age",
          ????????"size":?10
          ?}
          ????},
          ????"ageAvg":?{
          ??????"avg":?{
          ????????"field":?"age"
          ?}
          ????},
          ????"balanceAvg":?{
          ??????"avg":?{
          ????????"field":?"balance"
          ?}
          ? }
          ?}
          }

          檢索結(jié)果如下所示:

          hits 記錄返回了,三種聚合結(jié)果也返回了,平均年齡 34 隨,平均薪資 25208.0,品駿年齡分布:38 歲的有 2 個(gè),28 歲的有一個(gè),32 歲的有一個(gè)

          示例 1

          如果不想返回 hits 結(jié)果,可以在最后面設(shè)置 size:0

          GET?bank/_search
          {
          ??"query":?{
          ????"match":?{
          ??????"address":?"mill"
          ?}
          ??},
          ??"aggs":?{
          ????"ageAggr":?{
          ??????"terms":?{
          ????????"field":?"age",
          ????????"size":?10
          ?}
          ? }
          ??},
          ??"size":?0
          }
          • 示例 2:按照年齡聚合,并且查詢這些年齡段的平均薪資

          從結(jié)果可以看到 31 歲的有 61 個(gè),平均薪資 28312.9,其他年齡的聚合結(jié)果類似。

          示例 2
          • 示例 3:按照年齡分組,然后將分組后的結(jié)果按照性別分組,然后查詢出這些分組后的平均薪資
          GET?bank/_search
          {
          ??"query":?{
          ????"match_all":?{
          ?}
          ??},
          ??"aggs":?{
          ????"ageAggr":?{
          ??????"terms":?{
          ????????"field":?"age",
          ????????"size":?10
          ??????},
          ??????"aggs":?{
          ????????"genderAggr":?{
          ??????????"terms":?{
          ????????????"field":?"gender.keyword",
          ????????????"size":?10
          ??????????},
          ??????????"aggs":?{
          ????????????"balanceAvg":?{
          ??????????????"avg":?{
          ????????????????"field":?"balance"
          ? }
          ? }
          ? }
          ? }
          ? }
          ? }
          },
          ??"size":?0
          }

          從結(jié)果可以看到 31 歲的有 61 個(gè)。其中性別為?M?的 35 個(gè),平均薪資 29565.6,性別為?F?的 26 個(gè),平均薪資 26626.6。其他年齡的聚合結(jié)果類似。

          聚合結(jié)果

          5.2.9 Mapping 映射

          Mapping 是用來定義一個(gè)文檔 ( document ) ,以及它所包含的屬性 ( field ) 是如何存儲(chǔ)和索引的。

          • 定義哪些字符串屬性應(yīng)該被看做全文本屬性 ( full text fields )
          • 定義哪些屬性包含數(shù)字,日期或地理位置
          • 定義文檔中的所有屬性是否都能被索引 ( _all 配置 )
          • 日期的格式
          • 自定義映射規(guī)則來執(zhí)行動(dòng)態(tài)添加屬性

          Elasticsearch7 去掉 tpye 概念:

          關(guān)系型數(shù)據(jù)庫中兩個(gè)數(shù)據(jù)庫表示是獨(dú)立的,即使他們里面有相同名稱的列也不影響使用,但 ES 中不是這樣的。elasticsearch 是基于 Lucence 開發(fā)的搜索引擎,而 ES 中不同 type 下名稱相同的 field 最終在 Lucence 中的處理方式是一樣的。

          為了區(qū)分不同 type 下的同一名稱的字段,Lucence 需要處理沖突,導(dǎo)致檢索效率下降

          ES7.x 版本:URL 中的 type 參數(shù)為可選。

          ES8.x 版本:不支持 URL 中的 type 參數(shù)

          所有類型可以參考文檔:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

          • 查詢索引的映射

          如查詢 my-index 索引的映射

          GET?/my-index/_mapping
          返回結(jié)果:
          {
          ??"my-index"?:?{
          ????"mappings"?:?{
          ??????"properties"?:?{
          ????????"age"?:?{
          ??????????"type"?:?"integer"
          ????????},
          ????????"email"?:?{
          ??????????"type"?:?"keyword"
          ????????},
          ????????"employee-id"?:?{
          ??????????"type"?:?"keyword",
          ??????????"index"?:?false
          ????????},
          ????????"name"?:?{
          ??????????"type"?:?"text"
          ? }
          ?}
          ? }
          ?}
          }
          • 創(chuàng)建索引并指定映射

          如創(chuàng)建 my-index 索引,有三個(gè)字段 age,email,name,指定類型為 interge, keyword, text

          PUT?/my-index
          {
          ??"mappings":?{
          ????"properties":?{
          ??????"age":?{?"type":?"integer"?},
          ??????"email":?{?"type":?"keyword"??},
          ??????"name":?{?"type":?"text"?}
          ?}
          ?}
          返回結(jié)果:
          {
          ??"acknowledged"?:?true,
          ??"shards_acknowledged"?:?true,
          ??"index"?:?"my-index"
          }

          • 添加新的字段映射

          如在 my-index 索引里面添加 employ-id 字段,指定類型為 keyword

          PUT?/my-index/_mapping
          {
          ??"properties":?{
          ????"employee-id":?{
          ??????"type":?"keyword",
          ??????"index":?false
          ?}
          ?}
          }
          • 更新映射

          我們不能更新已經(jīng)存在的映射字段,必須創(chuàng)建新的索引進(jìn)行數(shù)據(jù)遷移。

          • 數(shù)據(jù)遷移

          POST?_reindex
          {
          ??"source":?{
          ????"index":?"twitter"
          ??},
          ??"dest":?{
          ????"index":?"new_twitter"
          ?}
          }

          六、中文分詞

          ES 內(nèi)置了很多種分詞器,但是對中文分詞不友好,所以我們需要借助第三方中文分詞工具包。

          6.1 ES 中的分詞的原理

          6.1.1 ES 的分詞器概念

          ES 的一個(gè)分詞器 ( tokenizer ) 接收一個(gè)字符流,將其分割為獨(dú)立的詞元 ( tokens ) ,然后輸出詞元流。

          ES 提供了很多內(nèi)置的分詞器,可以用來構(gòu)建自定義分詞器 ( custom ananlyzers )

          6.1.2 標(biāo)準(zhǔn)分詞器原理

          比如 stadard tokenizer 標(biāo)準(zhǔn)分詞器,遇到空格進(jìn)行分詞。該分詞器還負(fù)責(zé)記錄各個(gè)詞條 ( term ) 的順序或 position 位置 ( 用于 phrase 短語和 word proximity 詞近鄰查詢 ) 。每個(gè)單詞的字符偏移量 ( 用于高亮顯示搜索的內(nèi)容 ) 。

          6.1.3 英文和標(biāo)點(diǎn)符號分詞示例

          查詢示例如下:

          POST?_analyze
          {
          ??"analyzer":?"standard",
          ??"text":?"Do?you?know?why?I?want?to?study?ELK??2?3?33..."
          }

          查詢結(jié)果:

          do,?you,?know,?why,?i,?want,?to,?study,?elk,?2,3,33

          從查詢結(jié)果可以看到:

          (1)標(biāo)點(diǎn)符號沒有分詞。

          (2)數(shù)字會(huì)進(jìn)行分詞。

          英文句子分詞

          6.1.4 中文分詞示例

          但是這種分詞器對中文的分詞支持不友好,會(huì)將詞語分詞為單獨(dú)的漢字。比如下面的示例會(huì)將?悟空聊架構(gòu)?分詞為?,,,,構(gòu),期望分詞為?悟空,架構(gòu)。

          POST?_analyze
          {
          ??"analyzer":?"standard",
          ??"text":?"悟空聊架構(gòu)"
          }
          中文分詞悟空聊架構(gòu)

          我們可以安裝 ik 分詞器來更加友好的支持中文分詞。

          6.2 ?安裝 ik 分詞器

          6.2.1 ik 分詞器地址

          ik 分詞器地址:

          https://github.com/medcl/elasticsearch-analysis-ik/releases

          先檢查 ES 版本,我安裝的版本是?7.4.2,所以我們安裝 ik 分詞器的版本也選擇 7.4.2

          http://192.168.56.10:9200/
          {
          ??"name"?:?"8448ec5f3312",
          ??"cluster_name"?:?"elasticsearch",
          ??"cluster_uuid"?:?"xC72O3nKSjWavYZ-EPt9Gw",
          ??"version"?:?{
          ????"number"?:?"7.4.2",
          ????"build_flavor"?:?"default",
          ????"build_type"?:?"docker",
          ????"build_hash"?:?"2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
          ????"build_date"?:?"2019-10-28T20:40:44.881551Z",
          ????"build_snapshot"?:?false,
          ????"lucene_version"?:?"8.2.0",
          ????"minimum_wire_compatibility_version"?:?"6.8.0",
          ????"minimum_index_compatibility_version"?:?"6.0.0-beta1"
          ??},
          ??"tagline"?:?"You?Know,?for?Search"
          }
          選擇 ik 分詞器

          6.2.2 安裝 ik 分詞器的方式

          6.2.2.1 方式一:容器內(nèi)安裝 ik 分詞器

          • 進(jìn)入 es 容器內(nèi)部 plugins 目錄
          docker?exec?-it?<容器?id>?/bin/bash
          • 獲取 ik 分詞器壓縮包
          wget?https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
          • 解壓縮 ik 壓縮包
          unzip?壓縮包
          • 刪除下載的壓縮包
          rm?-rf?*.zip

          6.2.2.2 方式二:映射文件安裝 ik 分詞器

          進(jìn)入到映射文件夾

          cd?/mydata/elasticsearch/plugins

          下載安裝包

          wget?https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
          • 解壓縮 ik 壓縮包
          unzip?壓縮包
          • 刪除下載的壓縮包
          rm?-rf?*.zip

          6.2.2.3 方式三:Xftp 上傳壓縮包到映射目錄

          先用 XShell 工具連接虛擬機(jī) ( 操作步驟可以參考之前寫的文章 [02. 快速搭建 Linux 環(huán)境-運(yùn)維必備] ( http://www.jayh.club/#/05. 安裝部署篇/01. 環(huán)境搭建篇 )) ,然后用 Xftp 將下載好的安裝包復(fù)制到虛擬機(jī)。

          Xftp 上傳壓縮包

          6.3 解壓 ik 分詞器到容器中

          • 如果沒有安裝 unzip 解壓工具,則安裝 unzip 解壓工具。
          apt?install?unzip
          • 解壓 ik 分詞器到當(dāng)前目錄的 ik 文件夾下。

          命令格式:unzip

          實(shí)例:

          unzip?ELK-IKv7.4.2.zip?-d?./ik
          解壓 ik 分詞器
          • 修改文件夾權(quán)限為可讀可寫。
          chmod?-R?777?ik/
          • 刪除 ik 分詞器壓縮包
          rm?ELK-IKv7.4.2.zip

          6.4 檢查 ik 分詞器安裝

          • 進(jìn)入到容器中
          docker?exec?-it?<容器?id>?/bin/bash
          • 查看 Elasticsearch 的插件
          elasticsearch-plugin?list

          結(jié)果如下,說明 ik 分詞器安裝好了。是不是很簡單。

          ik
          ik 分詞器插件

          然后退出 Elasticsearch 容器,并重啟 Elasticsearch 容器

          exit
          docker?restart?elasticsearch

          6.5 使用 ik 中文分詞器

          ik 分詞器有兩種模式

          • 智能分詞模式 ( ik_smart )

          • 最大組合分詞模式 ( ik_max_word )

          我們先看下?智能分詞?模式的效果。比如對于?一顆小星星?進(jìn)行中文分詞,得到的兩個(gè)詞語:一顆、小星星

          我們在 Dev Tools Console 輸入如下查詢

          POST?_analyze
          {
          ??"analyzer":?"ik_smart",
          ??"text":?"一顆小星星"
          }

          得到如下結(jié)果,被分詞為 一顆和小星星。

          一顆小星星分詞結(jié)果

          再來看下?最大組合分詞模式。輸入如下查詢語句。

          POST?_analyze
          {
          ??"analyzer":?"ik_max_word",
          ??"text":?"一顆小星星"
          }

          一顆小星星?被分成了 6 個(gè)詞語:一顆、一、顆、小星星、小星、星星。

          一顆小星星分詞結(jié)果

          我們再來看下另外一個(gè)中文分詞。比如搜索悟空哥聊架構(gòu),期望結(jié)果:悟空哥、聊、架構(gòu)三個(gè)詞語。

          實(shí)際結(jié)果:悟、空哥、聊、架構(gòu)四個(gè)詞語。ik 分詞器將悟空哥分詞了,認(rèn)為?空哥?是一個(gè)詞語。所以需要讓 ik 分詞器知道?悟空哥?是一個(gè)詞語,不需要拆分。那怎么辦做呢?

          悟空哥聊架構(gòu)分詞

          6.5 自定義分詞詞庫

          6.5.1 自定義詞庫的方案

          • 方案

          新建一個(gè)詞庫文件,然后在 ik 分詞器的配置文件中指定分詞詞庫文件的路徑。可以指定本地路徑,也可以指定遠(yuǎn)程服務(wù)器文件路徑。這里我們使用遠(yuǎn)程服務(wù)器文件的方案,因?yàn)檫@種方案可以支持熱更新 ( 更新服務(wù)器文件,ik 分詞詞庫也會(huì)重新加載 ) 。

          • 修改配置文件

          ik 分詞器的配置文件在容器中的路徑:

          /usr/share/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml。

          修改這個(gè)文件可以通過修改映射文件,文件路徑:

          /mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml

          編輯配置文件:

          vim?/mydata/elasticsearch/plugins/ik/config/IKAnalyzer.cfg.xml

          配置文件內(nèi)容如下所示:



          <properties>
          ????<comment>IK?Analyzer?擴(kuò)展配置comment>
          ????
          ????<entry?key="ext_dict">custom/mydict.dic;custom/single_word_low_freq.dicentry>
          ?????
          ????<entry?key="ext_stopwords">custom/ext_stopword.dicentry>
          ?????
          ????<entry?key="remote_ext_dict">locationentry>
          ?????
          ????<entry?key="remote_ext_stopwords">http://xxx.com/xxx.dicentry>
          properties>

          修改配置?remote_ext_dict?的屬性值,指定一個(gè) 遠(yuǎn)程網(wǎng)站文件的路徑,比如 http://www.xxx.com/ikwords.text。

          這里我們可以自己搭建一套 nginx 環(huán)境,然后把 ikwords.text 放到 nginx 根目錄。

          6.5.2 搭建 nginx 環(huán)境

          方案:首先獲取 nginx 鏡像,然后啟動(dòng)一個(gè) nginx 容器,然后將 nginx 的配置文件拷貝到根目錄,再刪除原 nginx 容器,再用映射文件夾的方式來重新啟動(dòng) nginx 容器。

          • 通過 docker 容器安裝 nginx 環(huán)境。
          docker?run?-p?80:80?--name?nginx?-d?nginx:1.10
          • 拷貝 nginx 容器的配置文件到 mydata 目錄的 conf 文件夾
          cd?/mydata
          docker?container?cp?nginx:/etc/nginx?./conf
          • mydata 目錄 里面創(chuàng)建 nginx 目錄
          mkdir?nginx
          • 移動(dòng) conf 文件夾到 nginx 映射文件夾
          mv?conf?nginx/
          • 終止并刪除原 nginx 容器
          docker?stop?nginx
          docker?rm?<容器?id>
          • 啟動(dòng)新的容器
          docker?run?-p?80:80?--name?nginx?\
          -v?/mydata/nginx/html:/usr/share/nginx/html?\
          -v?/mydata/nginx/logs:/var/log/nginx?\
          -v?/mydata/nginx/conf:/etc/nginx?\
          -d?nginx:1.10
          • 訪問 nginx 服務(wù)
          192.168.56.10

          報(bào) 403 Forbidden, nginx/1.10.3 則表示 nginx 服務(wù)正常啟動(dòng)。403 異常的原因是 nginx 服務(wù)下沒有文件。

          • nginx 目錄新建一個(gè) html 文件
          cd?/mydata/nginx/html
          vim?index.html
          hello?passjava
          • 再次訪問 nginx 服務(wù)

          瀏覽器打印 hello passjava。說明訪問 nginx 服務(wù)的頁面沒有問題。

          • 創(chuàng)建 ik 分詞詞庫文件
          cd?/mydata/nginx/html
          mkdir?ik
          cd?ik
          vim?ik.txt

          填寫?悟空哥,并保存文件。

          • 訪問詞庫文件
          http://192.168.56.10/ik/ik.txt

          瀏覽器會(huì)輸出一串亂碼,可以先忽略亂碼問題。說明詞庫文件可以訪問到。

          • 修改 ik 分詞器配置
          cd?/mydata/elasticsearch/plugins/ik/config
          vim?IKAnalyzer.cfg.xml
          修改 ik 分詞器配置
          • 重啟 elasticsearch 容器并設(shè)置每次重啟機(jī)器后都啟動(dòng) elasticsearch 容器。
          docker?restart?elasticsearch
          docker?update?elasticsearch?--restart=always
          • 再次查詢分詞結(jié)果

          可以看到?悟空哥聊架構(gòu)?被拆分為?悟空哥、、架構(gòu)?三個(gè)詞語,說明自定義詞庫中的?悟空哥?有作用。

          自定義詞庫后的分詞結(jié)果
          —?【 THE END 】—
          本公眾號全部博文已整理成一個(gè)目錄,請?jiān)诠娞柪锘貜?fù)「m」獲取!


          3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。?!




          瀏覽 48
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日日夜夜精品视品 | 午夜福利淫秽视频 | 爱伊人久久 | 国产麻豆传媒视频 | 日韩五月天在线 |