大文本的全文檢索方案附件索引

一、簡介

Elasticsearch附件索引是需要插件支持的功能,它允許將文件內(nèi)容附加到Elasticsearch文檔中,并對這些附件內(nèi)容進行全文檢索。本文將帶你了解索引附件的原理和使用方法,并通過一個實際示例來說明如何在Elasticsearch中索引和檢索文件附件。

索引附件的核心原理是通過Ingest Attachment Processor將文件內(nèi)容轉(zhuǎn)換成Elasticsearch文檔中的字段。該插件使用Apache Tika來提取文檔中的附件內(nèi)容,并將其轉(zhuǎn)換為可索引的文本。

二、環(huán)境

version: '3.8'
services:
  cerebro:
    image: lmenezes/cerebro:0.8.3
    container_name: cerebro
    ports:
     - "9000:9000"
    command:
     - -Dhosts.0.host=http://eshot:9200
    networks:
     - elastic
  kibana:
    image: docker.elastic.co/kibana/kibana:8.1.3
    container_name: kibana
    environment:
      - I18N_LOCALE=zh-CN
      - XPACK_GRAPH_ENABLED=true
      - TIMELION_ENABLED=true
      - XPACK_MONITORING_COLLECTION_ENABLED="true"
      - ELASTICSEARCH_HOSTS=http://eshot:9200
      - server.publicBaseUrl=http://192.168.160.234:5601
    ports:
      - "5601:5601"
    networks:
      - elastic
  eshot:
    image: elasticsearch:8.1.3
    container_name: eshot
    environment:
      - node.name=eshot
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=hot
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\eshot\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\eshot\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    ports:
      - 9200:9200
    networks:
      - elastic
  eswarm:
    image: elasticsearch:8.1.3
    container_name: eswarm
    environment:
      - node.name=eswarm
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=warm
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\eswarm\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\eswarm\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    networks:
      - elastic
  escold:
    image: elasticsearch:8.1.3
    container_name: escold
    environment:
      - node.name=escold
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=eshot,eswarm,escold
      - cluster.initial_master_nodes=eshot,eswarm,escold
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - xpack.security.enabled=false
      - node.attr.node_type=cold
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - D:\zuiyuftp\docker\es8.1\escold\data:/usr/share/elasticsearch/data
      - D:\zuiyuftp\docker\es8.1\escold\logs:/usr/share/elasticsearch/logs
      - D:\zuiyuftp\docker\es8.1\eshot\plugins:/usr/share/elasticsearch/plugins
    networks:
      - elastic

# volumes:
#   eshotdata:
#     driver: local
#   eswarmdata:
#     driver: local
#   escolddata:
#     driver: local

networks:
  elastic:
    driver: bridge

三、安裝 ingest-attachment 插件

首先創(chuàng)建一個處理文本的管道,指定讀取文檔中content字段的內(nèi)容進行處理

PUT _ingest/pipeline/attachment
{
  "description" : "Extract attachment information",
  "processors" : [
    {
      "attachment" : {
        "field" : "content"
      }
    }
  ]
}

我們的elasticsearch版本是8.1,所以默認還是沒有內(nèi)置的,需要手動添加一下,因為我是docker啟動的,所以進入到docker容器內(nèi)部,執(zhí)行如下命令進行安裝

./bin/elasticsearch-plugin install ingest-attachment

安裝完成之后進行重啟elasticsearch集群進行激活插件的啟用

我這邊是三個節(jié)點,在hot節(jié)點下安裝完成之后只會在當前節(jié)點下有此插件

現(xiàn)在插件已經(jīng)安裝好了,繼續(xù)執(zhí)行剛才的定義文本處理通道進行創(chuàng)建

PUT _ingest/pipeline/attachment
{
  "description" : "Extract attachment information",
  "processors" : [
    {
      "attachment" : {
        "field" : "content"
      }
    }
  ]
}

在上面的定義中指定的attachment的過濾字段是content,所以我們在寫入elasticsearch索引內(nèi)容時,文件的內(nèi)容需要保存到content字段中

四、添加測試數(shù)據(jù)

下面我們創(chuàng)建一個保存文檔詳細信息的索引,比如文件題名,類型,文件內(nèi)容等字段

PUT /zfc-doc-000003
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "title":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}

通過上面兩步的操作之后我們的測試環(huán)境就算搭建完成了,下面就可以進行大文本內(nèi)容的讀取測試了,首先我們還是準備幾個測試的文本文件,比如txtdoc,pdf等類型的純文本文件

下面使用python腳本寫入索引內(nèi)容,首先安裝一下elasticsearch的相關(guān)依賴

pip install elasticsearch

下面是讀取文件夾C://Users//zuiyu//Documents//mydoc//20230806//demo//1下的所有文本文件保存到elasticsearch的索引zfc-doc-000003中的python腳本,保存為txt.py后面會用到

import os
from elasticsearch import Elasticsearch
import base64

# 定義Elasticsearch客戶端連接
es = Elasticsearch("http://localhost:9200")

# 定義索引名稱
index_name = "zfc-doc-000003"

# 定義文件夾路徑
folder_path = "C://Users//zuiyu//Documents//mydoc//20230806//demo//1"

# 遍歷文件夾下的所有文件
for root, dirs, files in os.walk(folder_path):
    for filename in files:
        # 構(gòu)建文件的完整路徑
        file_path = os.path.join(root, filename)

        # 讀取文件內(nèi)容,并以字節(jié)類型(bytes-like)返回
        with open(file_path, "rb") as file:
            file_content = file.read()

        # 使用base64.b64encode()函數(shù)將文件內(nèi)容轉(zhuǎn)換為base64編碼
        base64_content = base64.b64encode(file_content).decode("utf-8")

        # 構(gòu)建索引文檔
        document_body = {
            "title": filename,  # 使用文件名作為文檔標題
            "content": base64_content  # 將base64編碼后的內(nèi)容保存到字段 "content" 中
        }

        # 執(zhí)行索引操作,并指定pipeline為 "attachment"
        es.index(index=index_name, body=document_body, pipeline="attachment")

print("所有文件已成功保存到Elasticsearch索引中。")

該腳本中需要注意的點有如下三個

1、elasticsearch服務(wù)器地址

2、需要讀取的文件夾地址

3、保存的索引名稱與保存文本內(nèi)容的字段名稱

4、指定創(chuàng)建的pipeline

C://Users//zuiyu//Documents//mydoc//20230806//demo//1文件夾下有三個文件用來做測試,他們的文本內(nèi)容分別如下圖所示

其中為了方便測試,1.txt與2.txt僅有一句話

下面執(zhí)行python腳本txt.py保存到elasticsearchzfc-doc-000003中,并指定使用pipelineattachment

python txt.py

腳本執(zhí)行成功之后的截圖如下圖所示,輸出所有文件已成功保存到Elasticsearch索引中。即為成功導(dǎo)入

下面我們進行檢索驗證,因為上面咱們創(chuàng)建的索引中,文本內(nèi)容是保存到content字段中的,所以我們對content字段進行分詞檢索(content使用的是ik分詞器,不是很了解的可以參考之前的文章進行一下安裝)

1、首先檢索條件是內(nèi)容,預(yù)期結(jié)果是返回第一個文檔與第三個文檔

2、再次檢索mysql,返回第一個文檔

通過上面兩個小例子,可以驗證出來的結(jié)論就是,我們在文本內(nèi)容過大需要對內(nèi)容進行檢索時,可以使用提前指定的pipeline進行預(yù)處理

五、設(shè)置讀取文本范圍

Elasticsearch中,Ingest Attachment Processor插件的indexed_chars參數(shù)默認值是100000,表示將文本內(nèi)容的前100000保存在索引字段中

如果將其設(shè)置為-1,Elasticsearch會保存所有文本內(nèi)容。這可能會導(dǎo)致索引文檔過大,對性能和資源造成影響,特別是當處理大文本時。

為了避免索引文檔過大的問題,我們可以根據(jù)實際情況設(shè)置indexed_chars參數(shù),將其設(shè)置為較小的值,限制保存的字符數(shù)。這樣可以減小索引文檔的大小,降低Elasticsearch的負擔(dān)。

假如限制保存的字符數(shù)為50000,可以如下設(shè)置:

PUT _ingest/pipeline/attachment
{
  "description": "Pipeline for processing attachments",
  "processors": [
    {
      "attachment": {
        "field": "content",
        "indexed_chars": 50000
      }
    }
  ]
}

這樣,只有前50000個字符會被保存在content字段中,而超過這個字符數(shù)的部分則會被截斷,不會保存在索引中。

如果想單獨設(shè)定某個文檔的取值范圍,也可以在索引的文檔中指定字段值,舉例如下

PUT _ingest/pipeline/attachment_max
{
  "description" : "Extract attachment information",
  "processors" : [
    {
      "attachment" : {
        "field" : "content",
        "indexed_chars": 6,
        "indexed_chars_field" : "max_size",
      }
    }
  ]
}
PUT /zfc-doc-000005
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "title":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word"
      }
    }
  }
}
POST zfc-doc-000005/_doc?pipeline=attachment_max
{
  "id":"10",
"content":"5Litc2FkZ+eahOmqhOWCsuWIu+W9leacuuWNoea0m+aWr+Wkp+iSnOS7t+agvOWWgOS7gOinieW+l+aWr+WNoeaLiemjkuWNjg==",
  "max_size":10
}
POST zfc-doc-000005/_doc?pipeline=attachment_max
{
  "id":"11",
  "content":"5Litc2FkZ+eahOmqhOWCsuWIu+W9leacuuWNoea0m+aWr+Wkp+iSnOS7t+agvOWWgOS7gOinieW+l+aWr+WNoeaLiemjkuWNjg=="
}
GET zfc-doc-000005/_search
{
  "query": {
    "term": {
      "id": {
        "value": "11"
      }
    }
  }
}

使用"indexed_chars_field" : "max_size",指定文檔中的字段,根據(jù)文檔中的max_size字段來決定要取多少文本索引到字段中,如果文檔中沒有指定max_size則使用pipeline中指定的indexed_chars大小

六、移除二進制源文本

除了使用上述指定讀取文本文件的指定長度,還可以使用另一個參數(shù)"remove_binary": true控制來判斷是否保存二進制編碼的文本

PUT _ingest/pipeline/attachment_max
{
  "description" : "Extract attachment information",
  "processors" : [
    {
      "attachment" : {
        "field" : "content",
        "remove_binary": true
      }
    }
  ]
}

remove_binary 設(shè)置為true即不保存原始二進制文本,只會保存解析之后的結(jié)果,這種處理方式可以大大的減少存儲空間

七、優(yōu)點

  1. 輕量化索引文檔:使用Ingest Attachment Processor處理文本內(nèi)容時,只會將文本的元數(shù)據(jù)(例如文件路徑或URL)以及轉(zhuǎn)換后的attachment類型的內(nèi)容保存在索引文檔中,而不是保存整個文本內(nèi)容。這樣可以顯著減小索引文檔的大小,節(jié)省存儲空間,并提高索引和檢索的性能。

  2. 全文搜索功能:通過Pipeline中的Ingest Attachment Processor處理文本內(nèi)容后,Elasticsearch可以支持全文搜索功能,可以對文本進行全文檢索,查找包含指定關(guān)鍵詞的文檔。

  3. 靈活的數(shù)據(jù)處理:Pipeline機制允許在文本內(nèi)容存儲到Elasticsearch之前進行預(yù)處理??梢酝ㄟ^Pipeline添加其他處理器來進行數(shù)據(jù)轉(zhuǎn)換、清理或提取。

  4. 易于維護和擴展:使用Pipeline可以將數(shù)據(jù)處理邏輯與索引操作解耦,使代碼結(jié)構(gòu)更清晰,易于維護和擴展。如果以后有其他數(shù)據(jù)處理需求,只需要修改Pipeline而不需要修改索引操作。

  5. 可以實現(xiàn)附件類型:使用Ingest Attachment Processor可以將文本內(nèi)容轉(zhuǎn)換為attachment類型,這是Elasticsearch內(nèi)置的一種特殊數(shù)據(jù)類型,支持對文檔內(nèi)容的索引和全文檢索。

八、缺點

  1. 存儲需求:雖然使用attachment類型可以減小索引文檔的大小,但是仍然需要在Elasticsearch中存儲文本內(nèi)容的轉(zhuǎn)換結(jié)果。對于大量大文本內(nèi)容的情況,仍需要較大的存儲空間,并且最好使用"remove_binary": true移除二進制文本。

  2. 內(nèi)存消耗:在處理大文本內(nèi)容時,Ingest Attachment Processor需要將文本內(nèi)容暫存到內(nèi)存中進行處理,因此會消耗較多的內(nèi)存資源。如果處理大量大文本,可能導(dǎo)致內(nèi)存壓力增加,影響性能。

  3. 處理性能:雖然使用Pipeline可以在索引之前進行預(yù)處理,但Ingest Attachment Processor的處理速度仍然會受到限制。在處理大量大文本內(nèi)容時,可能導(dǎo)致處理速度較慢,影響索引性能。

  4. 不適用于實時場景:由于Ingest Attachment Processor處理文本內(nèi)容需要較多的計算和存儲資源,適用于離線或批處理的場景。對于實時索引或?qū)π阅芤筝^高的場景,可能需要考慮其他方案。

  5. 不支持所有文件類型:雖然attachment類型支持多種文件類型,但仍有一些特殊文件類型可能不受支持。在使用Pipeline中的Ingest Attachment Processor處理文本內(nèi)容時,需要注意文件類型的兼容性。

  6. 額外的配置和維護:使用Pipeline需要額外的配置和維護,需要定義處理器、設(shè)置參數(shù)等

  7. 依賴插件:Ingest Attachment ProcessorElasticsearch的一個插件,需要確保插件的版本與Elasticsearch版本兼容

九、總結(jié)

使用Pipeline中的Ingest Attachment Processor處理文本內(nèi)容可以在不影響檢索功能的前提下,優(yōu)化索引文檔的大小,提高索引和檢索的性能,并靈活地處理和擴展數(shù)據(jù)。這是處理大文本內(nèi)容時的一種高效和可靠的方式。雖然Pipeline中的Ingest Attachment Processor處理大文本內(nèi)容是一種高效和靈活的方式,但仍然存在一些挑戰(zhàn)和限制。在實際使用中,需要綜合考慮實際需求、資源限制和性能要求,選擇合適的處理方案。如果處理大量大文本或?qū)π阅芤筝^高,可能需要考慮其他優(yōu)化措施或方案。

十、需要注意的點

  1. 索引性能:處理大文本時,Pipeline的執(zhí)行可能會占用較多的CPU和內(nèi)存資源,特別是在處理多個大文本時。這可能會對Elasticsearch的索引性能和整體系統(tǒng)性能造成影響。在處理大文本之前,建議評估系統(tǒng)的性能和資源利用情況,確保系統(tǒng)有足夠的資源來執(zhí)行處理。

  2. 超時設(shè)置:Pipeline的執(zhí)行可能需要一定的時間,尤其是在處理大文本時。如果Pipeline的執(zhí)行時間超過了Elasticsearch的默認超時設(shè)置,可能會導(dǎo)致任務(wù)失敗。你可以通過設(shè)置timeout參數(shù)來延長超時時間,確保Pipeline有足夠的時間來執(zhí)行。

  3. 錯誤處理:在Pipeline的處理過程中,可能會出現(xiàn)各種錯誤,例如文本解析錯誤、索引失敗等。你需要注意適當處理這些錯誤,以避免任務(wù)失敗導(dǎo)致整個操作中斷??梢允褂眠m當?shù)漠惓L幚頇C制,或者使用ElasticsearchBulk API來進行批量索引,確保部分文檔處理失敗時,不會影響其他文檔的索引。

  4. 內(nèi)存管理:處理大文本時,可能會產(chǎn)生較大的臨時數(shù)據(jù),需要注意內(nèi)存的管理和及時釋放。確保處理過程中不會產(chǎn)生內(nèi)存泄漏或內(nèi)存溢出問題。

  5. 文件路徑安全性:如果使用文件路徑來索引文本內(nèi)容,需要注意文件路徑的安全性。確保文件路徑是合法的、可信的,并限制訪問范圍,避免可能的安全風(fēng)險。

  6. 版本兼容性:使用Pipeline時,需要注意插件的版本與Elasticsearch的版本兼容性。確保使用的Pipeline插件與Elasticsearch版本兼容,并定期升級插件以保持穩(wěn)定性和安全性。

總的來說,處理大文本時,需要綜合考慮性能、資源利用、錯誤處理等方面的問題,合理設(shè)計和優(yōu)化Pipeline的處理過程。在實際應(yīng)用中,可以進行壓力測試和性能測試,找到最合適的處理方案,確保系統(tǒng)能夠穩(wěn)定高效地處理大文本內(nèi)容。

參考鏈接

https://www.elastic.co/guide/en/elasticsearch/reference/8.9/attachment.html

如果感覺本文對你有所幫助歡迎點贊評論轉(zhuǎn)發(fā)收藏。如果你想了解更多關(guān)于ES的騷操作,更多實戰(zhàn)經(jīng)驗,歡迎關(guān)注。

原文鏈接:

https://mp.weixin.qq.com/s?__biz=MzIwNzYzODIxMw==&mid=2247486041&idx=1&sn=08e3b981c512a8a24afd3778cd3f231a&chksm=970e11f3a07998e5f7bbe017409944e4b57a0d800b2a149f7c291091f5b2b32b6493c3586257#rd

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

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

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