使用ES检索PDF或Word等格式文件方案

#大数据/ES #经验 #方案架构

ES检索PDF/Word等格式文件方案

插件安装

ES有文档预处理插件,但是7.x版本默认发版包不包含这个ingest attachment plugin

通过摄取附件插件,Elasticsearch 可以使用 Apache 文本提取库 Tika 提取常见格式的文件附件(如 PPT、XLS 和 PDF)。

源字段必须是 base64 编码的二进制文件。如果不想承担在 base64 之间来回转换的开销,可以使用 CBOR 格式而不是 JSON 格式,并将字段指定为字节数组而不是字符串表示。这样处理器就会跳过 base64 解码。

在线安装

以下命令直接联网下载插件并安装

sh 复制代码
sudo bin/elasticsearch-plugin install ingest-attachment

离线安装

官网有说:This plugin can be downloaded for offline install from https://artifacts.elastic.co/downloads/elasticsearch-plugins/ingest-attachment/ingest-attachment-7.3.2.zip.

shell 复制代码
./bin/elasticsearch-plugin install file:///opt/ingest-attachment-7.3.2.zip

注意:集群的所有ES服务实例都要安装这个插件!

最后,重启ElasticSearch全部服务。

构建管道

在Kibana中执行:

http 复制代码
PUT /_ingest/pipeline/attachment
{
    "description": "Extract attachment information",
    "processors": [
        {
            "attachment": {
                "field": "content",
                "ignore_missing": true
            }
        },
        {
            "remove": {
                "field": "content"
            }
        }
    ]
}

上述命令返回:

json 复制代码
{
  "acknowledged" : true
}

attachment中指定要预处理的字段为content,所以写入Elasticsearch时需要将文档内容放在content字段。

建立文档结构映射

为了提高搜索的效果,我们需要建立文档结构映射来定义文本文件通过预处理器上传后以何种形式存储。

使用PUT指令先创建一个docwrite的索引,用于接收测试数据。

首先,我们需要保证ES已经有中文分词器ik插件,这里不再赘述。

http 复制代码
PUT /docwrite
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "type":{
        "type": "keyword"
      },
      "attachment": {
        "properties": {
          "content":{
            "type": "text",
            "analyzer": "ik_smart"
          }
        }
      }
    }
  }
}

上述请求返回:

json 复制代码
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "docwrite"
}

attachment这个字段是attachment命名pipeline抽取文档附件中文本后自动附加的字段。这是一个嵌套字段,其包含多个子字段,包括抽取文本 content 和一些文档信息元数据。

测试

如文章开头所述,因ElasticSearch是基于JSON格式的文档数据库,所以附件文档在插入ElasticSearch之前必须进行Base64编码。先通过下面的网站将一个pdf文件转化为Base64的文本:

这是一个在线PDF转base64的小网站,有广告,有可能不可用:https://www.toolfk.com/tools/pdf-to-base64.html

使用上述网站只能转换点小文件(也可能是浏览器的问题),我转了一个10页的PPT后页面无响应,无法拷贝结果。

随后我转了一个更小PDF,可复制结果,发现字符数也有41万之多。

注意,ES默认限制一个字段只能索引最大10万个字符,因此需要修改前面的管道参数(改为100万),也可改为无限制但最好不要这样做:

http 复制代码
PUT /_ingest/pipeline/attachment
{
    "description": "Extract attachment information",
    "processors": [
        {
            "attachment": {
                "field": "content",
                "indexed_chars":1000000,
                "ignore_missing": true
            }
        },
        {
            "remove": {
                "field": "content"
            }
        }
    ]
}
# 这里,重新创建了一下索引

写入文档内容并索引

http 复制代码
POST /docwrite/_doc?pipeline=attachment
{
  "name":"性能分析排查思路",
  "type":"pdf",
  "url":"http://文件存储地址:8080/xxx/docs/raw/master/性能分析与内存问题排查思考.pdf",
  "content":"很长很长的base64内容粘贴到这了"
}

查询测试

http 复制代码
GET /docwrite/_search
{
  "query": {
    "match": {
      "attachment.content": {
        "query": "内存泄漏",
        "analyzer": "ik_smart"
      }
    }
  }
}

返回:能够查到1条结果(但目前只有这一条结果)。

作为对比,我们将本文档也转码为Base64格式上传上去。

然后继续搜索"内存泄漏"只出现了第一篇文档,而搜Base64则只出现了第二篇文档。

过程中解决了ES请求体过大和Kibana无法发送大请求的问题!(对于生产环境是必须的!)

结论

方案可行

后期,后端只需要使用Java API即可实现程序化转码PDF并上传。

建设思路

使用git hook实时监控触发,或者直接简单使用定时任务从文件源下载pdf、word、md等格式的文档,使用java将文档内容转成Base64格式,仿照上面的思路方法写入ES,就可实现全文搜索了,搜索到的文档可以返回文档的在线下载地址,可以直接打开或下载,完成闭环。

相关推荐
捂月7 分钟前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
瓜牛_gn33 分钟前
依赖注入注解
java·后端·spring
Estar.Lee1 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
喜欢猪猪1 小时前
Django:从入门到精通
后端·python·django
一个小坑货1 小时前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet271 小时前
【Rust练习】22.HashMap
开发语言·后端·rust
uhakadotcom1 小时前
如何实现一个基于CLI终端的AI 聊天机器人?
后端
Iced_Sheep2 小时前
干掉 if else 之策略模式
后端·设计模式
XINGTECODE2 小时前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
程序猿进阶2 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露