01.29 最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

簡介

You know, for search!

Elasticsearch 是一個開源的搜索引擎,建立在一個全文搜索引擎庫 Apache Lucene™ 基礎之上。Elasticsearch 也是使用 Java 編寫的,它的內部使用 Lucene 做索引與搜索,但是它的目的是使全文檢索變得簡單, 通過隱藏 Lucene 的複雜性,取而代之的提供一套簡單一致的 RESTful API。然而,Elasticsearch 不僅僅是 Lucene,並且也不僅僅只是一個全文搜索引擎。 它可以被下面這樣準確的形容:

  • 一個分佈式的實時文檔存儲,每個字段 可以被索引與搜索
  • 一個分佈式實時分析搜索引擎
  • 能勝任上百個服務節點的擴展,並支持 PB 級別的結構化或者非結構化數據

它提供了一個分佈式、支持多用戶的全文搜索引擎,具有HTTP Web接口和無模式JSON文檔。所有其他語言可以使用 RESTful API 通過端口 9200 和 Elasticsearch 進行通信

Elasticsearch是用Java開發的,並在Apache許可證下作為開源軟件發佈。官方客戶端在Java、.NET(C#)、PHP、Python、Apache Groovy、Ruby和許多其他語言中都是可用的。

根據DB-Engines的排名顯示,

Elasticsearch是最受歡迎的企業搜索引擎,其次是Apache Solr,也是基於Lucene。

Elasticsearch可以用於搜索各種文檔。它提供可擴展的搜索,具有接近實時的搜索,並支持多租戶。

Elasticsearch是分佈式的,這意味著索引可以被分成分片,每個分片可以有0個或多個副本。每個節點託管一個或多個分片,並充當協調器將操作委託給正確的分片。再平衡和路由是自動完成的。相關數據通常存儲在同一個索引中,該索引由一個或多個主分片和零個或多個複製分片組成。一旦創建了索引,就不能更改主分片的數量。

Elasticsearch 是一個實時的分佈式搜索分析引擎,它被用作全文檢索、結構化搜索、分析以及這三個功能的組合。

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

Elasticsearch 將所有的功能打包成一個單獨的服務,這樣你可以通過程序與它提供的簡單的 RESTful API 進行通信, 可以使用自己喜歡的編程語言充當 web 客戶端,甚至可以使用命令行(去充當這個客戶端)。

就 Elasticsearch 而言,起步很簡單。對於初學者來說,它預設了一些適當的默認值,並隱藏了複雜的搜索理論知識。 它 開箱即用 。只需最少的理解,你很快就能具有生產力。

Elasticsearch 是 面向文檔 的,意味著它存儲整個對象或 文檔。Elasticsearch 不僅存儲文檔,而且 索引每個文檔的內容使之可以被檢索。在 Elasticsearch 中,你 對文檔進行索引、檢索、排序和過濾--而不是對行列數據。

Elasticsearch 有2.x、5.x、6.x 三個大版本。更多瞭解可以訪問elastic中文社區

原理:倒排索引、分析、相關性排序

它基於Lucene,Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。在傳統全文檢索引擎的倒排索引的基礎上,實現了分塊索引。接下來介紹一下

倒排索引。

倒排索引(英語:Inverted index),也常被稱為反向索引、置入檔案或反向檔案,是一種索引方法,被用來存儲在全文搜索下某個單詞在一個文檔或者一組文檔中的存儲位置的映射。它是文檔檢索系統中最常用的數據結構。通過倒排索引,可以根據單詞快速獲取包含這個單詞的文檔列表。倒排索引主要由兩個部分組成:“單詞詞典”和“倒排文件”。

以下圖為例子:

假設我們有兩個文檔,每個文檔的 content 域包含如下內容:

  1. The quick brown fox jumped over the , lazy+ dog
  2. Quick brown foxes leap over lazy dogs in summer

反向索引:

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

如果我們想搜索 quick brown ,我們只需要查找包含每個詞條的文檔:

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

兩個文檔都匹配,但是第一個文檔比第二個匹配度更高。如果我們使用僅計算匹配詞條數量的簡單 相似性算法 ,那麼,我們可以說,對於我們查詢的相關性來講,第一個文檔比第二個文檔更佳。分析

分析

上面不太合理的地方:

  • Quick 和 quick 以獨立的詞條(token)出現,然而用戶可能認為它們是相同的詞。
  • fox 和 foxes 非常相似, 就像 dog 和 dogs ;他們有相同的詞根。
  • jumped 和 leap, 儘管沒有相同的詞根,但他們的意思很相近。他們是同義詞。

進行標準化

  • Quick 可以小寫化為 quick 。
  • foxes 可以 詞幹提取 --變為詞根的格式-- 為 fox 。類似的, dogs 可以為提取為 dog 。
  • jumped 和 leap 是同義詞,可以索引為相同的單詞 jump 。

標準化的反向索引:

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

對於查詢的字符串必須與詞條(token)進行相同的標準化處理,才能保證搜索的正確性。

分詞和標準化的過程稱為 分析 (analysis) :

  • 首先,將一塊文本分成適合於倒排索引的獨立的 詞條 , -> 分詞
  • 之後,將這些詞條統一化為標準格式以提高它們的“可搜索性” -> 標準化

分析工作是由分析器 完成的: analyzer

  • 字符過濾器首先,字符串按順序通過每個 字符過濾器 。他們的任務是在分詞前整理字符串。一個字符過濾器可以用來去掉HTML,或者將 & 轉化成 and。
  • 分詞器其次,字符串被 分詞器 分為單個的詞條。一個簡單的分詞器遇到空格和標點的時候,可能會將文本拆分成詞條。
  • Token 過濾器 (詞條過濾器)最後,詞條按順序通過每個 token 過濾器 。這個過程可能會改變詞條(例如,小寫化 Quick ),刪除詞條(例如, 像 a, and, the 等無用詞),或者增加詞條(例如,像 jump 和 leap 這種同義詞)。

相關性排序

默認情況下,搜索結果是按照 相關性 進行倒序排序的——最相關的文檔排在最前。

相關性可以用相關性評分表示,評分越高,相關性越高。

評分的計算方式取決於查詢類型 不同的查詢語句用於不同的目的: fuzzy 查詢(模糊查詢)會計算與關鍵詞的拼寫相似程度,terms 查詢(詞組查詢)會計算 找到的內容與關鍵詞組成部分匹配的百分比,但是通常我們說的 相關性 是我們用來計算全文本字段的值相對於全文本檢索詞相似程度的算法。

Elasticsearch 的相似度算法 被定義為檢索詞頻率/反向文檔頻率, TF/IDF ,包括以下內容:

  • 檢索詞頻率檢索詞在該字段出現的頻率?出現頻率越高,相關性也越高。 字段中出現過 5 次要比只出現過 1 次的相關性高。
  • 反向文檔頻率每個檢索詞在索引中出現的頻率?頻率越高,相關性越低。檢索詞出現在多數文檔中會比出現在少數文檔中的權重更低。
  • 字段長度準則字段的長度是多少?長度越長,相關性越低。 檢索詞出現在一個短的 title 要比同樣的詞出現在一個長的 content 字段權重更大。

elasticsearch python客戶端使用

  • 安裝
<code>pip install elasticsearch/<code>
  • 對於elasticsearch 5.x 版本 需要按以下方式導入
<code>from elasticsearch5 import Elasticsearch

# elasticsearch集群服務器的地址
ES = [
'127.0.0.1:9200'
]

# 創建elasticsearch客戶端
es = Elasticsearch(
ES,
# 啟動前嗅探es集群服務器
sniff_on_start=True,
# es集群服務器結點連接異常時是否刷新es結點信息
sniff_on_connection_fail=True,
# 每60秒刷新結點信息

sniffer_timeout=60
)/<code>
  • 搜索使用方式
<code>query = {
'query': {
'bool': {
'must': [
{'match': {'_all': 'python web'}}
],
'filter': [
{'term': {'status': 2}}
]
}
}
}
ret = es.search(index='articles', doc_type='article', body=query)/<code>

當然如果你想要在自己的Linux系統或者Windows中安裝Elasticsearch,可以參考百度中的各種答案,按照步驟一步一步來,本文就不具體介紹了。

分詞器我們以IK中文分析器為例:

安裝包可以去官網下載,或者私信我回復:IK 獲取。

  • 安裝
<code>sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install file:///home/python/elasticsearch-analysis-ik-5.6.16.zip/<code>
  • 重新啟動
<code>sudo systemctl restart elasticsearch/<code>
  • 測試分析器
<code>curl -X GET 127.0.0.1:9200/_analyze?pretty -d '
{
"analyzer": "standard",
"text": "我是&中國人"
}'

curl -X GET 127.0.0.1:9200/_analyze?pretty -d '
{
"analyzer": "ik_max_word",
"text": "我是&中國人"
}'/<code>

Elasticsearch 集群(cluster)

Elasticsearch 儘可能地屏蔽了分佈式系統的複雜性。這裡列舉了一些在後臺自動執行的操作:

  • 分配文檔到不同的容器 或 分片 中,文檔可以儲存在一個或多個節點中
  • 按集群節點來均衡分配這些分片,從而對索引和搜索過程進行負載均衡
  • 複製每個分片以支持數據冗餘,從而防止硬件故障導致的數據丟失
  • 將集群中任一節點的請求路由到存有相關數據的節點
  • 集群擴容時無縫整合新節點,重新分配分片以便從離群節點恢復

節點(node)

一個運行中的 Elasticsearch 實例稱為一個 節點,而集群是由一個或者多個擁有相同 cluster.name 配置的節點組成, 它們共同承擔數據和負載的壓力。當有節點加入集群中或者從集群中移除節點時,集群將會重新平均分佈所有的數據。

當一個節點被選舉成為 主 節點(master)時, 它將負責管理集群範圍內的所有變更,例如增加、刪除索引,或者增加、刪除節點等。 而主節點並不需要涉及到文檔級別的變更和搜索等操作,所以當集群只擁有一個主節點的情況下,即使流量的增加它也不會成為瓶頸。 任何節點都可以成為主節點。我們的示例集群就只有一個節點,所以它同時也成為了主節點。

作為用戶,我們可以將請求發送到 集群中的任何節點 ,包括主節點。 每個節點都知道任意文檔所處的位置,並且能夠將我們的請求直接轉發到存儲我們所需文檔的節點。 無論我們將請求發送到哪個節點,它都能負責從各個包含我們所需文檔的節點收集回數據,並將最終結果返回給客戶端。 Elasticsearch 對這一切的管理都是透明的。

分片(shard)

一個 分片 是一個底層的 工作單元 ,它僅保存了 全部數據中的一部分。

索引實際上是指向一個或者多個物理 分片 的 邏輯命名空間 。

文檔被存儲和索引到分片內,但是應用程序是直接與索引而不是與分片進行交互。

Elasticsearch 是利用分片將數據分發到集群內各處的。分片是數據的容器,文檔保存在分片內,分片又被分配到集群內的各個節點裡。 當你的集群規模擴大或者縮小時, Elasticsearch 會自動的在各節點中遷移分片,使得數據仍然均勻分佈在集群裡。

主分片(primary shard)

索引內任意一個文檔都歸屬於一個主分片,所以主分片的數目決定著索引能夠保存的最大數據量。

複製分片(副分片 replica shard)

一個副本分片只是一個主分片的拷貝。 副本分片作為硬件故障時保護數據不丟失的冗餘備份,併為搜索和返回文檔等讀操作提供服務。

在索引建立的時候就已經確定了主分片數,但是副本分片數可以隨時修改.

初始設置索引的分片方法

<code>PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
/<code>
  • number_of_shards每個索引的主分片數,默認值是 5 。這個配置在索引創建後不能修改。
  • number_of_replicas每個主分片的副本數,默認值是 1 。對於活動的索引庫,這個配置可以隨時修改。

2 個節點

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

3 個節點

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

分片是一個功能完整的搜索引擎,它擁有使用一個節點上的所有資源的能力。 我們這個擁有6個分片(3個主分片和3個副本分片)的索引可以最大擴容到6個節點,每個節點上存在一個分片,並且每個分片擁有所在節點的全部資源。

修改複製分片數目的方法

<code>PUT /blogs/_settings 

{
"number_of_replicas" : 2
}/<code>

擁有越多的副本分片時,也將擁有越高的吞吐量。

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

故障轉移 failover

最受歡迎的企業搜索引擎Elasticsearch在Python中的應用

  • 選舉新的主節點
  • 提升複製分片為主分片
  • 查看集群健康狀態

    <code>GET /_cluster/health

    {
    "cluster_name": "elasticsearch",
    "status": "green",
    "timed_out": false,
    "number_of_nodes": 1,
    "number_of_data_nodes": 1,
    "active_primary_shards": 0,
    "active_shards": 0,
    "relocating_shards": 0,
    "initializing_shards": 0,
    "unassigned_shards": 0
    }/<code>

    status 字段指示著當前集群在總體上是否工作正常。它的三種顏色含義如下:

    • green所有的主分片和副本分片都正常運行。
    • yellow所有的主分片都正常運行,但不是所有的副本分片都正常運行。
    • red有主分片沒能正常運行。

    當然Elasticsearch是一門水很深的技術,底層Lucene更為複雜,本文只是介紹了一下皮毛,後續可能會放出更多的相關知識技術,敬請關注。

    作者簡介:Python菜鳥工程師,將在接下來的一段時間內與大家分享一些與Python相關的知識點。如若文中出現問題,各位大佬多多指點,互相學習。喜歡的關注一個吧!謝謝!


    分享到:


    相關文章: