使用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,就可实现全文搜索了,搜索到的文档可以返回文档的在线下载地址,可以直接打开或下载,完成闭环。

相关推荐
小_太_阳35 分钟前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
Mitch31143 分钟前
【漏洞复现】CVE-2015-3337 Arbitrary File Reading
elasticsearch·网络安全·docker·漏洞复现
智慧老师44 分钟前
Spring基础分析13-Spring Security框架
java·后端·spring
Mitch3111 小时前
【漏洞复现】CVE-2015-5531 Arbitrary File Reading
web安全·elasticsearch·网络安全·docker·漏洞复现
搬码后生仔2 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
凡人的AI工具箱2 小时前
每天40分玩转Django:Django国际化
数据库·人工智能·后端·python·django·sqlite
喝醉酒的小白3 小时前
Elasticsearch(ES)监控、巡检及异常指标处理指南
大数据·elasticsearch·搜索引擎
Lx3523 小时前
Pandas数据重命名:列名与索引为标题
后端·python·pandas
小池先生3 小时前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
百罹鸟3 小时前
【vue高频面试题—场景篇】:实现一个实时更新的倒计时组件,如何确保倒计时在页面切换时能够正常暂停和恢复?
vue.js·后端·面试