这是stackoverflow上一篇精彩的问答。git
原文不大好理解,我作了梳理+图解;github
原文是ES早期版本,部分写法已不适用,全部DSL我在6.X上进行了重写和验证;web
针对原文内容作了扩展。docker
从新审视一个停滞不前的项目,并寻求建议,对数千个“旧”文档进行现代化改造,数据库
最终指望效果:经过网络访问这些文档。
文档以各类格式存在,有些已通过时:
- .doc,
- PageMaker,
- 硬拷贝hardcopy (OCR),
- PDFbash
不少文档已经被转化成扫描版的PDF,以前咱们认为PDF类型是最终的文档格式,如今看来,咱们想听听建议(好比:xml是否是更好呢?)网络
核心需求点:curl
一、一旦全部文档都采用通用格式,咱们但愿经过网页界面提供其内容并提供搜索服务。elasticsearch
二、咱们但愿经过搜索,可以灵活地只返回整个文档的部分页面(我相信的Lucene / elasticsearch使这成为可能?!?)svg
三、若是全部文档是XML是否会更加灵活?
四、如何存储、在哪里存储XML?是直接存储在数据库中仍是存储成文件系统中的文件?关于文档中的嵌入式图像/图表呢?
以上,但愿获得回复。
注解:xml只是提问者的当时初步的理解。
我将推荐ElasticSearch,咱们先解决这个问题并讨论如何实现它:
这有几个部分:
ElasticSearch能够提供什么:
【直译】您能够将整个文档做为附件发送到ElasticSearch,而且能够进行全文搜索。可是关键点在于上面的(4)和(5):知道你文档中的位置,并返回文档的某些部分。存储单个页面可能足以知足您的“我在哪里”的目的,可是您但愿将它们分组,以便在搜索结果中返回文档,即便搜索关键字出如今不一样的页面上。
任务分解:
使用Tika(或任何你喜欢的)来从每一个文档中提取文本。将其保留为纯文本或HTML格式以保留一些格式。
(忘记XML,不须要它)。
每一个文档提取元数据:标题,做者,章节,语言,日期等。
将原始文档存储在您的文件系统中,并记录路径,以便之后可使用。
在ElasticSearch中,索引包含全部元数据和可能的章节列表的“doc”文档。
将每一个页面索引为“page”文档,其中包含:
- 包含“doc”文档ID的父字段(请参阅下面的“父子关系”)
- 文本
- 页码
- 也许章节标题或编号
- 您想要搜索的任何元数据
存储必备——父子文档关系:
一般,在ES(和大多数NoSQL解决方案)中,每一个文档/对象都是独立的 - 没有真正的关系。
经过创建“doc”和“page”之间的父子关系,ElasticSearch确保子文档(即“页面”)与父文档(“doc”)存储在同一分片上。
这使您可以运行has_child等的查询方式,它将根据“page”的内容找到最匹配的“doc”。
图解示例:
2、检索部分——
如今进行搜索。
你如何作到这一点取决于你想如何展现你的结果
经过页面的结果很容易。
此查询返回匹配页面的列表(每一个页面所有返回)以及页面中高亮显示的片断列表。
举例以下:
POST /my_index/page/_search?pretty=1
{
"query" : {
"match" : {
"text" : "interesting keywords"
}
},
"highlight": {
"pre_tags": [
"<span style=\"color:red\">"
],
"post_tags": [
"</span>"
],
"require_field_match": true,
"fields": {
"title": {}
}
}
}
显示包含文本高亮字段的“doc”分组有点棘手。 它不能用一个单一的查询来完成。
一种方法多是:
第1步:经过对其子(“页面”)查询,返回最匹配的父级(“doc”)。
POST /my_index/doc/_search?pretty=1
{
"query": {
"has_child": {
"type": "page",
"query": {
"bool": {
"must": [
{
"match": {
"text": "interesting keywords"
}
},
{
"term": {
"type": "page"
}
},
{
"term": {
"factor": "5"
}
}
]
}
},
"score_mode": "sum"
}
}
}
第2步:从上述查询中收集“doc”ID 发出新查询,从匹配的“页面”文档中获取片断。
GET /my_index/page/_search?pretty=1
{
"query" : {
"bool" : {
"must":{
"query" : {
"match" : {
"text" : "interesting keywords"
}
}},
"filter" : {
"terms" : {
"doc_id" : [1,2,3]
}
}
}
},
"highlight" : {
"fields" : {
"text" : {}
}
}
}
第3步:在您的应用程序中,将上述查询的结果按doc分组并显示出来。
使用第二个查询的搜索结果,您已经拥有了可供显示的页面的全文。要转到下一页,您能够搜索它:
GET /my_index/page/_search?pretty=1
{
"query" : {
"constant_score" : {
"filter" :
[
{
"term" : {
"doc_id" : 1
}
},
{
"term" : {
"page" : 2
}
}
]
}
},
"size" : 1
}
或者,给“页面”文档提供一个由 page_num(例如123_2)组成的ID,而后您能够经过以下的检索获取该页面:
curl -XGET'http://127.0.0.1:9200/my_index/page/123_2
Tika是一个内容分析工具,自带全面的parser工具类,能解析基本全部常见格式的文件,获得文件的metadata,content等内容,返回格式化信息。总的来讲能够做为一个通用的解析工具。特别对于搜索引擎的数据抓去和处理步骤有重要意义。
Tika是Apache的Lucene项目下面的子项目,在lucene的应用中可使用tika获取大批量文档中的内容来创建索引,很是方便,也很容易使用。
Apache Tika toolkit能够自动检测各类文档(如word,ppt,xml,csv,ppt等)的类型并抽取文档的元数据和文本内容。
Tika集成了现有的文档解析库,并提供统一的接口,使针对不一样类型的文档进行解析变得更简单。Tika针对搜索引擎索引、内容分析、转化等很是有用。
Ambar是一个开源文搜索引擎,具备自动抓取,OCR识别,标签分类和即时全文搜索功能。
Ambar定义了在工做流程中实现全文本文档搜索的新方法:
参考:
2018-06-07 22:43 思于家中床前
做者:铭毅天下
转载请标明出处,原文地址:
https://blog.csdn.net/laoyang360/article/details/80616320 若是感受本文对您有帮助,请点击‘顶’支持一下,您的支持是我坚持写做最大的动力,谢谢!