Elasticsearch检索PDF和Office文档的方案测评

前言

这段时间主要攻关了一下Elasticsearch的一些特性,发觉Elasticsearch还是个挺牛逼的玩意儿,我以前经常用它存日志,还没想着拿来存别的东西,一般不都SQL嘛,但是我看了一下现在流行的检索方案,基本都是elasticsearch做检索引擎,说明这个东西经历了时间的考研,用了的人都说好。

我以前拿Elasticsearch来存储日志,搜东西相当方便,定义好检索语句直接走你,但是我看百度文库搜索,还可以做到docx,pdf关键字检索并且高亮,这个就很厉害了,这两天紧急攻关了一下,把自己踩的坑和收获记录下来,方便未来自己复习/查看

需求分析

老样子,写任何blog,我都要做需求分析,这样才能更好的进行开发和写作。

我们要干嘛

我们要实现一个elasticsearch检索pdf和office家族文件的功能,并且要对pdf/office文件进行一个全文检索,也就是说,搜索“Yemilice”,不仅仅是标题含有“Yemilice”,内容含有“Yemilice”的文件也要检索出来,并且给人家高亮。

我们的工作环境

底层环境

Centos7服务器

Elasticsearch的版本

6.3.2

现有的检索解决方案

经过我的发力工作(Google/baidu),现在市面上流行这么几种方案

  1. Elasticsearch 官方插件 ingest-attachment
  2. 第三方开源服务 fscrawler
  3. 大数据平台 Ambari

接下来麻烦事儿就来了,这三个方案,到底选哪个?才能更那啥呢,我倒不如把他们一一实现一遍,然后给大家伙儿展示一拨,然后最后再选一个合适的不就得了嘛!

没事儿,苦了我一个,幸福大家伙儿呗!

1. ingest-attachment插件

这玩意儿是什么呢,说白了就是elasticsearch官方给大家贡献的一个插件,支持你把docx,pdf之类的东西导入到es当中。当然要你自己手动去实现接口。

1.1 ingest-attachment插件的安装

首先,我认为你现在在CN境内,你就不要看网上那些老哥教的直接执行

1
./elasticsearch-plugin install ingest-attachment

这样你会等到地老天荒也下载不完,现在你需要的就是下个离线包,然后再去安装

下载离线包的网址

1
https://artifacts.elastic.co/downloads/elasticsearch-plugins/ingest-attachment/ingest-attachment-6.3.2.zip.

注意一点啊,一定要注意!你的ingest-attachment版本必须和你的elasticsearch一致,你要强行不听我的,到时候费心思整完,弄不好,那你就只能来颗华子再来一次了。

安装离线包

1
./elasticsearch-plugin install ingest-attachment-6.3.2.zip

没报错就说明你安上了,不放心的话

1
./elasticsearch-plugin list

看一下,有这个插件了说明你已经有了这个插件

1.2 ingest-attachment插件的基础使用

看了下官网,其实他的逻辑很简单,整个管道,你把你的pdf/doc什么的给转成base64,然后通过管道把base64传进去,es会把所有的东西给你安排好。

我现在简单的整了个pdf,名字就叫1.pdf,现在开始吧。

抽取管道的函数编写,这里是告诉es,创建一个抽取管道pipeline

1
2
3
4
5
6
7
8
9
10
11
12
13
curl -X PUT "localhost:9200/_ingest/pipeline/attachment" -d '{
"description" : "Extract attachment information",
"processors":[
{
"attachment":{
"field":"data",
"indexed_chars" : -1,
"ignore_missing":true
}
},
{
"remove":{"field":"data"}
}]}'

创建一个index(表),名字叫pdf,设定1个分片(单节点,当然你自己可以改)

1
2
3
4
5
6
7
8
9
10
curl --location --request PUT '127.0.0.1:9200/pdf' \
--header 'Content-Type: application/json' \
-d '{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 0
}
}
}'

将pdf转为base64编码,然后上传到elasticsearch当中

这里网上那个方法是直接perl调base64,我这里一直报错,如果和我一样的老哥,用我下面给得另一种方法

方法1

1
2
3
4
curl --location --request PUT '10.0.7.234:9200/pdf/pdf/1?pipeline=attachment' \
--header 'Content-Type: application/json' \
-d '{ "data":" '`base64 -w 0 /root/pdf/pdf.pdf | perl -pe's/\n/\\n/g'`'"
}'

方法2

直接导入base64码

1
2
3
4
curl --location --request PUT '10.0.7.234:9200/pdf/pdf/1?pipeline=attachment' \
--header 'Content-Type: application/json' \
-d '{ "data":"JVBERi0xLjcNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFuZyh6aC1DTikgL1N0cnVjdFRyZWVSb290IDE1IDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4vTWV0YWRhdGEgMzMgMCBSL1ZpZXdlclByZWZlcmVuY2VzIDM0IDAgUj4+DQplbmRvYmoNC......(这里我不展示完了)"
}'

现在去查看index(表)

显示了作者,之类的杂七杂八信息,而content就是详细的全文,可以直接搜索,因为有我的大名我就马赛克了。。

这就导入了,搜索也是按一般的搜索方法

1
2
3
4
5
6
7
8
9
GET pdf/_search
{

"query": {
"match": {
"attachment.content": "pdf"
}
}
}

1.3 ingest-attachment插件的性能评测

测试导入PDF(10M大小,无图片)

base64命令在perl中执行了大概2s左右,

并且CPU/内存 在转换->存储这个阶段,占用了

可见在抽取文本 ——> 传输存储入es的时候,插件可能会占用少部分CPU

测试导入PDF(40M大小,图片/文字混用)

base64命令在perl中执行了大概10s左右,并且还返回了错误(perl长度过大的错误)

并且CPU/内存 在转换->存储这个阶段,占用了

在图片/文字混用并且pdf文件比较大的情况下,内存占用较大,并且返回较慢,这里需要注意,并且解析的base64会直接塞到系统内存当中,如果做多文件抽取,可能会有CPU/内存占用较大的情况出现。

1.4 ingest-attachment插件的优缺点

优点:

  1. 安装方便,只需要下载zip安装包,调用elasticsearch本身自带的安装模块即可
  2. 使用方便,编辑一条管道抽取命令,可以直接利用linux的base64命令转码存入elasticsearch中
  3. 支持的格式比较多,支持ppt,pdf,doc,docx,xls等office常用的办公软件格式导入到elasticsearch当中。
  4. 导入后的文档可以直接输入中文进行检索

缺点:

  1. 大文件支持不够,如果超过100M的pdf,base64转码将比较缓慢,并且,存入到elasticsearch中的数据也十分庞大
  2. 必须要将文件下载到本地,然后必须进行base64转码才可以存到elasticsearch中,等于说,必须要实体文件,因为需要base64转码,如果文件在对象存储/云上,那就不可以这么操作了
  3. 对于pdf,doc中含有图片的情况,没有办法将图片中文文字识别出来,而且如果出现图片较多的情况,转码较慢,含有特殊字符的base64码导入也会无法识别。

1.5 ingest-attachment插件的使用场景

  1. 存储的文件不那么大的情况
  2. 存储的文件大部分都是纯文字的情况
  3. 存储的文件全文搜索精准度要求不那么高

2. fscrawler服务

一个类似filebeat的监控服务,监控某个文件夹下面的文档,定时去遍历一次,如果发现了新添加的文档则会直接写入到elasticsearch当中。

2.1 fscrawler安装

首先非常重要的一点,确定你的elasticseach版本,

如果你的版本 <= 6.3.2,那你需要下载2.5 版本的fscrawler,这个非常重要,否则是无法启动任务的!!!!

1
https://repo1.maven.org/maven2/fr/pilato/elasticsearch/crawler/fscrawler/2.5/fscrawler-2.5.zip

如果你的版本 > 6.3.2, 你就可以随意选择2.6,2.7的fscrawler了,区别还是有一些的,后面我会说。

下载下来,解压,这个你肯定会

1
unzip fscrawler-2.5.zip

尝试跑一下

1
./fscrawler

输出

1
2
3
03:53:39,425 INFO  [f.p.e.c.f.c.FsCrawler] No job specified. Here is the list of existing jobs:
03:53:39,433 INFO [f.p.e.c.f.c.FsCrawler] [1] - work01
03:53:39,433 INFO [f.p.e.c.f.c.FsCrawler] Choose your job [1-1]...

说明能用

2.2 fscrawler的使用方法

启动服务

查看一下文件结构

编写指定的json去进行服务监控/设置

现在导入一个1.pdf的文件

监控到fscrawler发生了变化

去查看elasticsearch,已经有了这个1.pdf的文件

2.3 fscrawler的配置文件解析(彩蛋)

一般来说,咱们fscrawler的配置文件都是默认在/root/.fscrawler/_settings.json下的,但是,如果你的es版本高于6.3.2,你下载的fs版本不是2.5,那么你的settings文件将会是yaml格式的,不知道是不是在向filebeat看齐。。。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
// 工程名
"name" : "work01",
"fs" : {
// 监控的文件夹
"url" : "/tmp/es",
// 多长时间去扫描一次
"update_rate" : "30s",
// 添加例外
"excludes" : [ "*/~*" ],
"json_support" : false,
// 将文件名作为ID
"filename_as_id" : false,
// 文件大小添加
"add_filesize" : true,
// 同步删除
"remove_deleted" : true,
"add_as_inner_object" : false,
"store_source" : false,
"index_content" : true,
"attributes_support" : false,
"raw_metadata" : true,
"xml_support" : false,
"index_folders" : true,
"lang_detect" : false,
"continue_on_error" : false,
// ocr开启
"pdf_ocr" : true,
"ocr" : {
// ocr英文
"language" : "eng"
}
},
"elasticsearch" : {
"nodes" : [ {
// esip
"host" : "127.0.0.1",
"port" : 9200,
"scheme" : "HTTP"
} ],
"bulk_size" : 100,
"flush_interval" : "5s",
"byte_size" : "10mb"
},
"rest" : {
"scheme" : "HTTP",
"host" : "127.0.0.1",
"port" : 8080,
"endpoint" : "fscrawler"
}
}

2.4 fscrawler的性能评测

首先走一波导入文件测试

导入1M纯文字的pdf

瞬间就完成了,速度极快

elasticsearch监控信息如下

Fscrawler占用CPU/内存如下

导入10M纯文字的pdf

瞬间就完成了,速度极快

elasticsearch监控信息如下

Fscrawler占用CPU/内存如下

导入40M文字图片都有的pdf

速度很快,但是CPU占比一下就上去了,es还是没有什么变化

elasticsearch监控信息如下

Fscrawler占用CPU/内存如下

2.5 fscrawler的优缺点

fscrawler我其实是比较推荐的

优点

  1. 支持的格式很多,并且自带OCR,如果内存/CPU富裕的情况可以直接上OCR,识别率虽然不是特别高但也够用了。
  2. 导入不用自己动手,设置好配置之后,fscrawler会帮你创建好index,然后自动导入文件
  3. 支持文件过滤,如果监控的文件夹里面闲杂文件比较多可以写正则过滤掉
  4. CPU/内存占比比较低,我是用的自己的虚拟机,导入40Mpdf完全无问题,CPU占比上去了一瞬间就降下来了。

缺点

  1. 结合我们的使用场景,我们的文件在远端,需要下载下来,下载到指定文件夹,但是下载到指定文件夹后,fscrawler不会马上导入,是去定时扫描,下载到本地的话可能会把系统盘内存撑满,加快扫描时间会让CPU占比上升
  2. 安装部署比较麻烦,需要自己写service,自己写维护
  3. 配置文件需要自己定义,容错有问题,如果es down机,原有的文件发送一遍失败之后,不会继续发送

3. Ambari服务

这个有个很奇葩的点,是要Es去依赖它,而不是它依赖Es,这东西本身是做大数据的!我感觉咱都有Es了还要啥自行车!

这个是做大数据用的,安装一个大概1个多G,但是功能比较全面,支持各种大文件导入,还支持图片文字的读取,自动分词之类的,其实还是很好用。

3.1 使用一波Ambari

Ambari的安装就不在这里介绍了。。这个安装比较复杂,但是网上大部分都是docker集成的,我们现在的环境没有docker,所以我只有手动安装了,在我的机器已经安上了,现在需要安装Ambari的Elasticsearch插件

1
wget https://community.hortonworks.com/storage/attachments/87416-elasticsearch-mpack-2600-9.tar.gz

安装mpack

1
ambari-server install-mpack --mpack=/path/to/87416-elasticsearch-mpack-2600-9.tar.gz --verbose

重启ambari-server

1
ambari-server restart

在ambari-server 上部署elasticsearch

1
curl --user admin:admin -i -H 'X-Requested-By: ambari' -X GET "http://ambari.server:8080/api/v1/clusters/$cluster_name/configurations?type=cluster-env"

启动elasticsearch

1
systemctl restart elasticsearch

现在可以在Ambari的管理页面看到es服务器了

设置ambar的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
my-files:
depends_on:
serviceapi:
condition: service_healthy
image: ambar/ambar-local-crawler
restart: always
networks:
- internal_network
expose:
- "8082"
environment:
- name=my-files
- ignoreFolders=**/ForSharing/**
- ignoreExtensions=.{exe,dll,rar}
- ignoreFileNames=*backup*
- maxFileSize=15mb
volumes:
- /media/Docs:/usr/data

现在尝试导入一个PDF

1
2
3
4
curl -X POST \
http://ambar/api/files/Books/1984-george_orwell.pdf \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F 1984-george_orwell.rtf=@1984-george_orwell.pdf

这下就完成了导入

3.2 高级特性

监控S3对象存储

设定ak,sk

1
2
echo ACCESS_KEY_ID:SECRET_ACCESS_KEY >  ~/.passwd-s3fs
chmod 600 ~/.passwd-s3fs

挂载s3 bucket

1
mkdir /mnt/s3-bucket

添加挂载到fstab中

1
mybucket /mnt/s3-bucket fuse.s3fs _netdev,allow_other 0 0

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
my-files:
depends_on:
serviceapi:
condition: service_healthy
image: ambar/ambar-local-crawler
restart: always
networks:
- internal_network
expose:
- "8082"
environment:
- name=my-files
- ignoreFolders=**/ForSharing/**
- ignoreExtensions=.{exe,dll,rar}
- ignoreFileNames=*backup*
- maxFileSize=15mb
volumes:
- /media/Docs:/mnt/s3-bucket

OCR文件识别

ambari自带强势的ocr识别,可以识别多种文字/字母/格式的文件,但是需要富裕的CPU和内存

3.3 可能会出现的问题

优点

  1. 它可以很好地处理大文件(> 100 MB)
  2. 它从PDF中提取内容(即使格式不佳并带有嵌入式图像),并对图像进行OCR
  3. 它为用户提供了简单易用的REST API和WEB UI
  4. 部署非常容易(感谢Docker)
  5. 它是根据Fair Source 1 v0.9许可开源的
  6. 开箱即用地为用户提供解析和即时搜索体验。

缺点

  1. 部署可能会相当麻烦,没有docker部署,单独部署的话配置比较复杂
  2. OCR会占用大量的CPU/内存
  3. 如果不是大数据,有些大材小用了

4. 总结

我都分析成这样了,该用哪个,心里是不是有点数了,其实很简单

当你的pdf/doc文件不大的情况下,上ingest-attachment插件

当你的文件经常发生变动,上fscrawler

当你是大数据老哥,上Ambari

今天的文章就到这,憋了个大的,如果帮到你,我很开心。

end

2020-07-29

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • © 2019-2022 Yemilice lau
  • Powered by Hexo Theme Ayer
  • PV: UV:

觉得帮到你了么?赏我点儿~

支付宝
微信