乐趣区

关于后端:大文本的全文检索方案附件索引

一、简介

Elasticsearch附件索引是须要插件反对的性能,它容许将文件内容附加到 Elasticsearch 文档中,并对这些附件内容进行全文检索。本文将带你理解索引附件的原理和应用办法,并通过一个理论示例来阐明如何在 Elasticsearch 中索引和检索文件附件。

索引附件的外围原理是通过 Ingest Attachment Processor 将文件内容转换成 Elasticsearch 文档中的字段。该插件应用 Apache Tika 来提取文档中的附件内容,并将其转换为可索引的文本。

二、环境

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 插件

首先创立一个解决文本的管道,指定读取文档中 content 字段的内容进行解决

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

咱们的 elasticsearch 版本是 8.1,所以默认还是没有内置的,须要手动增加一下,因为我是docker 启动的,所以进入到 docker 容器外部,执行如下命令进行装置

./bin/elasticsearch-plugin install ingest-attachment

装置实现之后进行重启 elasticsearch 集群进行激活插件的启用

我这边是三个节点,在 hot 节点下装置实现之后只会在以后节点下有此插件

当初插件曾经装置好了,继续执行方才的定义文本处理通道进行创立

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

在下面的定义中指定的 attachment 的过滤字段是 content,所以咱们在写入elasticsearch 索引内容时,文件的内容须要保留到 content 字段中

四、增加测试数据

上面咱们创立一个保存文档详细信息的索引,比方文件题名,类型,文件内容等字段

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

通过下面两步的操作之后咱们的测试环境就算搭建实现了,上面就能够进行大文本内容的读取测试了,首先咱们还是筹备几个测试的文本文件,比方 txtdocpdf 等类型的纯文本文件

上面应用 python 脚本写入索引内容,首先装置一下 elasticsearch 的相干依赖

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:
        # 构建文件的残缺门路
        file_path = os.path.join(root, filename)

        # 读取文件内容,并以字节类型(bytes-like)返回
        with open(file_path, "rb") as file:
            file_content = file.read()

        # 应用 base64.b64encode()函数将文件内容转换为 base64 编码
        base64_content = base64.b64encode(file_content).decode("utf-8")

        # 构建索引文档
        document_body = {
            "title": filename,  # 应用文件名作为文档题目
            "content": base64_content  # 将 base64 编码后的内容保留到字段 "content" 中
        }

        # 执行索引操作,并指定 pipeline 为 "attachment"
        es.index(index=index_name, body=document_body, pipeline="attachment")

print("所有文件已胜利保留到 Elasticsearch 索引中。")

该脚本中须要留神的点有如下三个

1、elasticsearch服务器地址

2、须要读取的文件夹地址

3、保留的索引名称与保留文本内容的字段名称

4、指定创立的pipeline

C://Users//zuiyu//Documents//mydoc//20230806//demo//1文件夹下有三个文件用来做测试,他们的文本内容别离如下图所示

其中为了不便测试,1.txt 与 2.txt 仅有一句话

上面执行 python 脚本 txt.py 保留到 elasticsearchzfc-doc-000003中,并指定应用 pipelineattachment

python txt.py

脚本执行胜利之后的截图如下图所示,输入 所有文件已胜利保留到 Elasticsearch 索引中。即为胜利导入

上面咱们进行检索验证,因为下面咱们创立的索引中,文本内容是保留到 content 字段中的,所以咱们对 content 字段进行分词检索(content应用的是ik 分词器,不是很理解的能够参考之前的文章进行一下装置)

1、首先检索条件是 内容,预期后果是返回第一个文档与第三个文档

2、再次检索mysql,返回第一个文档

通过下面两个小例子,能够验证进去的论断就是,咱们在文本内容过大须要对内容进行检索时,能够应用提前指定的 pipeline 进行预处理

五、设置读取文本范畴

Elasticsearch 中,Ingest Attachment Processor插件的 indexed_chars 参数默认值是 100000,示意将文本内容的前100000 保留在索引字段中

如果将其设置为 -1Elasticsearch 会保留所有文本内容。这可能会导致索引文档过大,对性能和资源造成影响,特地是当解决大文本时。

为了防止索引文档过大的问题,咱们能够依据理论状况设置 indexed_chars 参数,将其设置为较小的值,限度保留的字符数。这样能够减小索引文档的大小,升高 Elasticsearch 的累赘。

如果限度保留的字符数为50000,能够如下设置:

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

这样,只有前 50000 个字符会被保留在 content 字段中,而超过这个字符数的局部则会被截断,不会保留在索引中。

如果想独自设定某个文档的取值范畴,也能够在索引的文档中指定字段值,举例如下

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", 指定文档中的字段,依据文档中的max_size 字段来决定要取多少文本索引到字段中,如果文档中没有指定 max_size 则应用 pipeline 中指定的 indexed_chars 大小

六、移除二进制源文本

除了应用上述指定读取文本文件的指定长度,还能够应用另一个参数 "remove_binary": true 管制来判断是否保留二进制编码的文本

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

remove_binary 设置为 true 即不保留原始二进制文本,只会保留解析之后的后果,这种解决形式能够大大的缩小存储空间

七、长处

  1. 轻量化索引文档:应用 Ingest Attachment Processor 解决文本内容时,只会将文本的元数据(例如文件门路或 URL)以及转换后的 attachment 类型的内容保留在索引文档中,而不是保留整个文本内容。这样能够显著减小索引文档的大小,节俭存储空间,并进步索引和检索的性能。
  2. 全文搜寻性能:通过 Pipeline 中的 Ingest Attachment Processor 解决文本内容后,Elasticsearch能够反对全文搜寻性能,能够对文本进行全文检索,查找蕴含指定关键词的文档。
  3. 灵便的数据处理:Pipeline机制容许在文本内容存储到 Elasticsearch 之前进行预处理。能够通过 Pipeline 增加其余处理器来进行数据转换、清理或提取。
  4. 易于保护和扩大:应用 Pipeline 能够将数据处理逻辑与索引操作解耦,使代码构造更清晰,易于保护和扩大。如果当前有其余数据处理需要,只须要批改 Pipeline 而不须要批改索引操作。
  5. 能够实现附件类型:应用 Ingest Attachment Processor 能够将文本内容转换为 attachment 类型,这是 Elasticsearch 内置的一种非凡数据类型,反对对文档内容的索引和全文检索。

八、毛病

  1. 存储需要:尽管应用 attachment 类型能够减小索引文档的大小,然而依然须要在 Elasticsearch 中存储文本内容的转换后果。对于大量大文本内容的状况,仍须要较大的存储空间,并且最好应用 "remove_binary": true 移除二进制文本。
  2. 内存耗费:在解决大文本内容时,Ingest Attachment Processor须要将文本内容暂存到内存中进行解决,因而会耗费较多的内存资源。如果解决大量大文本,可能导致内存压力减少,影响性能。
  3. 解决性能:尽管应用 Pipeline 能够在索引之前进行预处理,但 Ingest Attachment Processor 的处理速度依然会受到限制。在解决大量大文本内容时,可能导致处理速度较慢,影响索引性能。
  4. 不适用于实时场景:因为 Ingest Attachment Processor 解决文本内容须要较多的计算和存储资源,实用于离线或批处理的场景。对于实时索引或对性能要求较高的场景,可能须要思考其余计划。
  5. 不反对所有文件类型:尽管 attachment 类型反对多种文件类型,但仍有一些非凡文件类型可能不受反对。在应用 Pipeline 中的 Ingest Attachment Processor 解决文本内容时,须要留神文件类型的兼容性。
  6. 额定的配置和保护:应用 Pipeline 须要额定的配置和保护,须要定义处理器、设置参数等
  7. 依赖插件:Ingest Attachment ProcessorElasticsearch 的一个插件,须要确保插件的版本与 Elasticsearch 版本兼容

九、总结

应用 Pipeline 中的 Ingest Attachment Processor 解决文本内容能够在不影响检索性能的前提下,优化索引文档的大小,进步索引和检索的性能,并灵便地解决和扩大数据。这是解决大文本内容时的一种高效和牢靠的形式。尽管 Pipeline 中的 Ingest Attachment Processor 解决大文本内容是一种高效和灵便的形式,但依然存在一些挑战和限度。在理论应用中,须要综合思考理论需要、资源限度和性能要求,抉择适合的解决计划。如果解决大量大文本或对性能要求较高,可能须要思考其余优化措施或计划。

十、须要留神的点

  1. 索引性能:解决大文本时,Pipeline的执行可能会占用较多的 CPU 和内存资源,特地是在解决多个大文本时。这可能会对 Elasticsearch 的索引性能和整体零碎性能造成影响。在解决大文本之前,倡议评估零碎的性能和资源利用状况,确保零碎有足够的资源来执行解决。
  2. 超时设置:Pipeline的执行可能须要肯定的工夫,尤其是在解决大文本时。如果 Pipeline 的执行工夫超过了 Elasticsearch 的默认超时设置,可能会导致工作失败。你能够通过设置 timeout 参数来缩短超时工夫,确保 Pipeline 有足够的工夫来执行。
  3. 错误处理:在 Pipeline 的处理过程中,可能会呈现各种谬误,例如文本解析谬误、索引失败等。你须要留神适当解决这些谬误,以防止工作失败导致整个操作中断。能够应用适当的异样解决机制,或者应用 ElasticsearchBulk API来进行批量索引,确保局部文档解决失败时,不会影响其余文档的索引。
  4. 内存治理:解决大文本时,可能会产生较大的长期数据,须要留神内存的治理和及时开释。确保处理过程中不会产生内存透露或内存溢出问题。
  5. 文件门路安全性:如果应用文件门路来索引文本内容,须要留神文件门路的安全性。确保文件门路是非法的、可信的,并限度拜访范畴,防止可能的平安危险。
  6. 版本兼容性:应用 Pipeline 时,须要留神插件的版本与 Elasticsearch 的版本兼容性。确保应用的 Pipeline 插件与 Elasticsearch 版本兼容,并定期降级插件以放弃稳定性和安全性。

总的来说,解决大文本时,须要综合思考性能、资源利用、错误处理等方面的问题,正当设计和优化 Pipeline 的处理过程。在理论利用中,能够进行压力测试和性能测试,找到最合适的解决计划,确保零碎可能稳固高效地解决大文本内容。

参考链接

https://www.elastic.co/guide/en/elasticsearch/reference/8.9/a…

如果感觉本文对你有所帮忙欢送点赞评论转发珍藏。如果你想理解更多对于 ES 的骚操作,更多实战经验,欢送关注。

原文链接:

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

本文由 mdnice 多平台公布

退出移动版