用 Python 優雅地玩轉 Elasticsearch:實用技巧與最佳實踐

大数据技术前线發表於2024-03-15

來源:銘毅天下Elasticsearch

Elasticsearch,這個開源的分散式搜尋與資料分析引擎,因其強大的全文搜尋功能而廣受歡迎。

儘管Elasticsearch的核心是用Java編寫的,它提供了REST API,讓各種程式語言的開發者都能輕鬆與之互動,Python當然也不例外。

今天,我們將深入探討如何將 Elasticsearch 與 Python 結合使用,提升我們的專案到新的高度。

用 Python 優雅地玩轉 Elasticsearch:實用技巧與最佳實踐

1、入門準備

首先,確保我們有一個執行中的 Elasticsearch 8.X 例項、Kibana例項。

用 Python 優雅地玩轉 Elasticsearch:實用技巧與最佳實踐

部署搭建細節推薦閱讀《一本書講透Elasticsearch》第 3 章 Elasticsearch 叢集部署。

2、Elasticsearch Python 客戶端介紹

在Python專案中,我們可以選擇以下幾個庫與Elasticsearch互動:

elasticsearch-py:官方提供的低階客戶端(Official low-level client for Elasticsearch),直接且靈活。

elasticsearch-dsl:基於 elasticsearch-py 的高階封裝,簡化了很多操作,更適合日常使用。

django-elasticsearch-dsl:為 Django 使用者設計,基於elasticsearch-dsl,實現了與Django的深度整合。

3、Elasticsearch Python 客戶端適用場景及優缺點

客戶端應用場景優點缺點
elasticsearch-py直接與Elasticsearch互動的底層操作- 完整訪問Elasticsearch API
- 靈活性高
- 程式碼複雜,易出錯
- 需要深入理解ES的查詢DSL
elasticsearch-dsl構建複雜搜尋查詢- 簡化查詢構建
- 更Pythonic的介面
- 減少語法錯誤的風險
- 學習成本相對較高
django-elasticsearch-dsl在Django專案中使用Elasticsearch- 與Django無縫整合
- 自動同步Django模型與Elasticsearch文件
- 限定於Django專案
- 相比直接使用elasticsearch-py有更多抽象

4、使用 elasticsearch-py 進行增刪改查基礎操作

elasticsearch-py 是Elasticsearch的官方低階Python客戶端。

它允許我們執行所有基本和高階的Elasticsearch操作,包括直接與叢集互動、管理索引、執行CRUD(建立、讀取、更新、刪除)操作以及搜尋。

以下是使用elasticsearch-py的一些基礎操作示例:

4.1 匯入依賴

匯入必要的Python庫,包括datetime、Elasticsearch、configparser,並配置警告過濾以忽略警告資訊。

from elasticsearch import Elasticsearch
import configparser
import warnings

warnings.filterwarnings("ignore")

4.2 初始化Elasticsearch客戶端

init_es_client函式從配置檔案config.ini讀取Elasticsearch的配置(如主機地址、使用者名稱和密碼),並初始化Elasticsearch客戶端。這允許與Elasticsearch叢集建立連線。

def init_es_client(config_path='./conf/config.ini'):
"""初始化並返回Elasticsearch客戶端"""
# 初始化配置解析器
config = configparser.ConfigParser()
# 讀取配置檔案
config.read(config_path)
# 從配置檔案中獲取Elasticsearch配置
es_host = config.get('elasticsearch', 'ES_HOST')
es_user = config.get('elasticsearch', 'ES_USER')
es_password = config.get('elasticsearch', 'ES_PASSWORD')

es = Elasticsearch(
hosts=[es_host],
basic_auth=(es_user, es_password),
verify_certs=False,
ca_certs='conf/http_ca.crt'
)
return es
basic_auth=(es_user, es_password)

Elasticsearch 8.X要求客戶端連線時進行身份驗證。這裡使用基本認證(HTTP Basic Authentication)提供使用者名稱和密碼。這兩個值應該對應於有效的Elasticsearch使用者憑證,該使用者需要有足夠的許可權執行客戶端請求的操作。

verify_certs=False

這個選項告訴客戶端是否驗證Elasticsearch伺服器的TLS證書。在生產環境中,我們應該將其設定為True以確保安全的通訊。將此設定為False可能會導致中間人攻擊等安全風險。在開發或測試環境中,如果使用的是自簽名證書,可能需要暫時設定為False來避免驗證錯誤。

ca_certs='conf/http_ca.crt'

當verify_certs=True時,這裡指定了CA證書的路徑,客戶端將使用它來驗證伺服器證書的簽名。這是實現TLS加密通訊的關鍵部分。在Elasticsearch 8.X中,如果啟用了安全特性(預設情況下啟用),那麼客戶端需要信任連線到的Elasticsearch伺服器使用的CA。如果Elasticsearch使用的是自簽名證書或私有CA簽發的證書,那麼我們需要在客戶端提供CA證書的路徑。

對於Elasticsearch 8.X版本,正確配置客戶端以安全地連線到Elasticsearch服務是非常重要的。這包括使用HTTPS協議、提供正確的使用者認證憑證,以及在啟用了TLS加密通訊時驗證伺服器證書。為了最大化安全性和相容性,強烈推薦在生產環境中使用由受信任CA簽發的證書,並且始終驗證伺服器證書。

4.3 建立索引

create_index函式嘗試建立一個新索引。如果指定的索引名已存在,則忽略建立操作。索引是資料儲存和搜尋的基本單位。

def create_index(es, index_name="test-index"):
"""建立索引,如果索引已存在則忽略"""
if not es.indices.exists(index=index_name):
es.indices.create(index=index_name)

4.4 定義對映

define_mapping函式為索引設定對映。對映定義了索引中文件的欄位型別,如文字、整數和關鍵詞等。這有助於Elasticsearch理解欄位內容並最佳化搜尋和聚合操作。

def define_mapping(es, index_name="test-index"):
"""為索引定義對映"""
mapping = {
"mappings": {
"properties": {
"name": {"type": "text"},
"age": {"type": "integer"},
"email": {"type": "keyword"}
}
}
}
es.indices.create(index=index_name, body=mapping, ignore=400) # ignore=400忽略索引已存在錯誤

4.5 插入文件

insert_document函式向指定索引插入(或更新)一個文件。文件由一個Python字典表示,可以包含多個欄位和值。如果提供了doc_id,該ID將用於文件;否則,Elasticsearch會自動生成一個ID。

def insert_document(es, index_name="test-index", doc_id=None, document=None):
"""插入文件到指定索引"""
es.index(index=index_name, id=doc_id, document=document)

4.6 更新文件

update_document函式更新指定索引中的特定文件。需要文件的ID和要更新的欄位。

def update_document(es, index_name="test-index", doc_id=None, updated_doc=None):
"""更新指定ID的文件"""
es.update(index=index_name, id=doc_id, body={"doc": updated_doc})

4.7 刪除文件

delete_document函式從指定索引中刪除特定ID的文件。

def delete_document(es, index_name="test-index", doc_id=None):
"""刪除指定ID的文件"""
es.delete(index=index_name, id=doc_id)

4.8 搜尋文件

search_documents 函式在指定索引中執行搜尋查詢,並返回匹配的文件。查詢透過一個查詢DSL(Domain-Specific Language)構建,可以非常靈活地定義搜尋條件。

def search_documents(es, index_name="test-index", query=None):
"""在指定索引中搜尋文件"""
return es.search(index=index_name, body=query)

4.9 main函式

main函式是程式的入口點,按順序執行了建立索引、定義對映、插入文件、更新文件、搜尋文件和刪除文件的操作,演示了與Elasticsearch互動的完整流程。

def main():
# 初始化Elasticsearch客戶端
es = init_es_client()

# 建立索引
create_index(es)

# 定義對映
define_mapping(es)

# 插入文件
doc = {
"name": "John Doe",
"age": 30,
"email": "john.doe@example.com"
}
insert_document(es, doc_id="1", document=doc)

# 更新文件
# 注意:這裡假設我們知道文件的ID。實際使用時可能需要透過搜尋等方式來確定ID
update_document(es, doc_id="1", updated_doc={"age": 31})

# 搜尋文件
query = {
"query": {
"match": {
"name": "John Doe"
}
}
}
search_result = search_documents( es, query=query )
print( search_result )

# 刪除文件
delete_document(es, doc_id="1")

以上示例展示了使用elasticsearch-py進行基本的Elasticsearch操作。

這些操作涵蓋了建立和刪除索引、定義對映、插入、更新和刪除文件以及基本的搜尋功能。

elasticsearch-py提供了訪問Elasticsearch強大功能的直接途徑,但正如之前討論的,使用它需要對Elasticsearch的工作原理有深入理解。

5、使用 elasticsearch-dsl 進行基礎操作

如下程式碼演示瞭如何使用elasticsearch-dsl,一個Python庫,以便與Elasticsearch進行高效互動。

我們將涵蓋初始化客戶端、建立索引、文件的CRUD操作以及執行搜尋查詢。

5.1 初始化 Elasticsearch 客戶端

為了與Elasticsearch叢集互動,首先需要建立連線。我們透過讀取配置檔案來獲取連線資訊,並建立一個預設連線。

def init_es_client_dsl(config_path='./conf/config.ini'):
config = configparser.ConfigParser()
config.read(config_path)
es_host = config.get('elasticsearch', 'ES_HOST')
es_user = config.get('elasticsearch', 'ES_USER')
es_password = config.get('elasticsearch', 'ES_PASSWORD')

connections.create_connection(
hosts=[es_host],
http_auth=(es_user, es_password),
verify_certs=False
)

5.2 建立索引

在Elasticsearch中,索引是儲存文件的容器。我們定義了一個文件類 MyDocument,指定了索引名稱和對映,並刪除已存在的同名索引後重新建立。

class MyDocument(Document):
name = Text()
age = Integer()
email = Text()

class Index:
name = 'test-index'
settings = { "number_of_shards": 1, }

def create_index_dsl():
es = connections.get_connection()
es.indices.delete(index='test-index', ignore=[400, 404])
MyDocument.init()

5.3 插入文件

將一個新文件插入到Elasticsearch。如果提供了id,將使用它作為文件ID;否則,Elasticsearch會自動生成一個。

def insert_document_dsl(document):
doc = MyDocument(meta={'id': document.get('id', None)}, **document)
doc.save()

5.4 更新文件

根據文件ID更新已存在的文件。這裡我們更新了文件的某些欄位。

def update_document_dsl(doc_id, updated_doc):
doc = MyDocument.get(id=doc_id)
for key, value in updated_doc.items():
setattr(doc, key, value)
doc.save()

5.5 刪除文件

根據ID刪除指定的文件。

def delete_document_dsl(doc_id):
doc = MyDocument.get(id=doc_id)
doc.delete()

5.6 搜尋文件

執行一個搜尋查詢,返回匹配指定查詢條件的文件。在此例中,我們使用match查詢匹配名字欄位。

def search_documents_dsl(query):
es = connections.get_connection()
es.indices.refresh(index="test-index")

s = Search(index="test-index").query("match", name=query)
response = s.execute()
return response

5.7 主函式

main_ds l函式串聯了上述所有步驟,展示瞭如何在實際應用中使用這些功能。

def main_dsl():
init_es_client_dsl()
create_index_dsl()
insert_document_dsl({ ... })
results = search_documents_dsl('John Doe')
update_document_dsl('1', { ... })
delete_document_dsl('1')

5.8 執行

將上述程式碼儲存為Python檔案並執行,可以看到從插入到搜尋、更新和刪除文件的完整流程。

用 Python 優雅地玩轉 Elasticsearch:實用技巧與最佳實踐

5.9 特別強調——預設連線池管理

在elasticsearch-dsl中,當我們建立查詢或者執行任何需要與Elasticsearch伺服器通訊的操作時,並不需要每次都顯式地指定Elasticsearch連線例項。

這是因為elasticsearch-dsl內部維護了一個預設的連線池。當我們首次使用connections.create_connection函式建立連線時,如果不指定別名,這個連線就被設定為預設連線。

官方alias 示例:

from elasticsearch_dsl import connections

connections.create_connection(alias='my_new_connection', hosts=['localhost'], timeout=60)

後續的所有操作,如搜尋查詢,都會自動使用這個預設連線,除非咱們透過using引數顯式指定了另一個連線。

這種設計使得在大多數情況下,我們只需在應用啟動時建立一次連線,而不需要在每個查詢中重複指定連線資訊,從而簡化了程式碼並提高了程式碼的可讀性和維護性。

參見:

configuration.html#default-connection

6、小結

篇幅原因,django-elasticsearch-dsl API 沒有展開。如果需要,歡迎留言討論。

在本文中,我們探討了如何將Elasticsearch與Python結合使用,透過兩種主要的Python客戶端——elasticsearch-py和elasticsearch-dsl。

elasticsearch-py提供了直接且靈活的底層API訪問,適用於需要完整控制Elasticsearch互動細節的場景。

相比之下,elasticsearch-dsl提供了更高階的抽象,透過更為Pythonic的介面簡化了複雜搜尋查詢的構建,使得程式碼更加簡潔易讀,尤其適合日常使用和複雜查詢構建。

用 Python 優雅地玩轉 Elasticsearch:實用技巧與最佳實踐

此外,我們還介紹瞭如何透過elasticsearch-dsl內部管理的預設連線池來簡化連線管理,避免了在每次查詢時重複指定連線資訊,從而提高了開發效率和程式碼的可維護性。透過這種方式,開發者只需在應用啟動時配置一次連線,之後便可以在整個應用中複用這個預設連線。

無論是直接使用elasticsearch-py進行底層操作,還是利用elasticsearch-dsl進行更加高效的資料處理和搜尋,Elasticsearch都能為Python開發者提供強大的搜尋和資料分析能力,幫助他們輕鬆應對各種資料處理和搜尋需求,將專案提升到新的高度。在選擇合適的客戶端和API時,重要的是根據專案的具體需求和團隊的熟悉程度來做出決策,以確保既能充分發揮Elasticsearch的強大功能,又能保持程式碼的可讀性和可維護性。

來自 “ ITPUB部落格 ” ,連結:https://blog.itpub.net/70027827/viewspace-3009052/,如需轉載,請註明出處,否則將追究法律責任。

相關文章