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


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

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

    插件安装

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

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

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

    在线安装

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

    sudo bin/elasticsearch-plugin install ingest-attachment
    
    • 1

    离线安装

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

    ./bin/elasticsearch-plugin install file:///opt/ingest-attachment-7.3.2.zip
    
    • 1

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

    最后,重启ElasticSearch全部服务。

    构建管道

    在Kibana中执行:

    PUT /_ingest/pipeline/attachment
    {
        "description": "Extract attachment information",
        "processors": [
            {
                "attachment": {
                    "field": "content",
                    "ignore_missing": true
                }
            },
            {
                "remove": {
                    "field": "content"
                }
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上述命令返回:

    {
      "acknowledged" : true
    }
    
    • 1
    • 2
    • 3

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

    建立文档结构映射

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

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

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

    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"
              }
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    上述请求返回:

    {
      "acknowledged" : true,
      "shards_acknowledged" : true,
      "index" : "docwrite"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    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万),也可改为无限制但最好不要这样做:

    PUT /_ingest/pipeline/attachment
    {
        "description": "Extract attachment information",
        "processors": [
            {
                "attachment": {
                    "field": "content",
                    "indexed_chars":1000000,
                    "ignore_missing": true
                }
            },
            {
                "remove": {
                    "field": "content"
                }
            }
        ]
    }
    # 这里,重新创建了一下索引
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    写入文档内容并索引

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

    查询测试

    GET /docwrite/_search
    {
      "query": {
        "match": {
          "attachment.content": {
            "query": "内存泄漏",
            "analyzer": "ik_smart"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

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

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

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

    结论

    方案可行

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

    建设思路

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

  • 相关阅读:
    软考-计算机网络与系统安全
    tf.dtypes
    PPO算法经典论文阅读
    PPT的结构设计
    浅谈JavaScript中的forEach、for in和for of循环的基本用法和区别。
    大数据-数据分析初步学习,待补充
    课程表系列
    第八章 小程序后端开发
    Redis不止能存储字符串,还有List、Set、Hash、Zset,用对了能给你带来哪些优势?
    C++(List的模拟实现)
  • 原文地址:https://blog.csdn.net/yuand7/article/details/136436712