搜索,已经成为我们生活中必不可少的一个重要部分,无论我们是在网上冲浪、工作办公、还是私人文件的处理,都需要一个搜索框方便我们快速找到所需的信息。而当我们的任务是需要对多个信息渠道中的信息进行梳理和检索时,现有割裂的各个搜索框无法协同的问题,就成了阻碍我们进一步提高效率的痛点。我的日常生活和工作就经常有这样一个场景:
“客户询问一个问题,与这个问题相关的知识点我记忆中在什么地方见过,可能是我读过的某篇文章,或者是某封邮件,甚至是我自己在某个文件里记录了笔记,但我就是记不起来在哪里了,然后就各种翻浏览记录和本地的文件,却依然无法找到”
因此,构建一个全方位的信息检索系统,能够连接多个数据源从日常工作接触的所有渠道上去寻找信息的这样一个工具成了不少企业和个人的强烈需求。而在本文,我们将进行一个简单的展示,通过Elastic Search Platform (我们以前称为Elastic Stack),我们能在一天之内就构建一个涵盖从互联网到本地文件的全方位的信息检索系统。
分步一个全方位的信息检索系统
构建一个全方位的信息检索系统,我们至少需要以下几个步骤:
确定信息检索系统所需的数据源
首先,我们要确定哪些数据应该包含在这个系统当中。
从我个人的需求看,一个全方位的信息检索系统主要包含两个方面的内容,一个是本地的文件资料,一个是网络上的有用资源。
所以,在构建的第一步上,我们需要先梳理哪些信息是我们在平时的工作习惯中经常需要接触,并且反复查询的。
以我本身的工作为例,围绕elasticsearch相关的项目、主题,在日常工作中我需要经常进行的工作包括:
- 检索elasticsearch本身的官方文档,以回答用户的具体技术问题
- 检索以往整理好的项目建设、架构、健康巡检、故障排查、最佳实践等内容,以方便应对场景化的问题并重复利用已有的资源解决相似的问题
- 检索公司内的共享资源,包括产品团队,开发团队,以及其他架构师整理好的各种产品、销售相关的资料
- 检索互联网上社区爱好者的各种关于项目应用、疑难杂症相关的博客、分享,以广泛了解用户的各种反馈和经验总结
对应的,以上内容主要涉及以下信息:
- 本地官方文档,为了避免在没有外网的环境,或者外网环境不佳的情况下也能够顺利查询文档,我在本地保存了一份7.10.1的elasticsearch的文档
- 本地与工作相关的文件、记录、代码。类型包括:markdown, docx, pptx, pdf, png, jpeg, gif... 等各种类型的文件
- 公司在google driver,wiki page上的所有共享内容。(因为公司本身提供了集成了这些内容的workplace search,在本教程中不再演示)
- 互联网上的各种有用的网址,包括但不限于:
因此,对于上述的数据,我们需要有针对性的使用能够一次性扫描,定期获取更新的工具将这些数据摄入到检索系统当中
使用Web crawler爬取Elasticsearch相关的网络资源
对于网络上的信息,主要的工具是爬虫,在这个例子中,需要使用爬虫获取的资源包括:
- https://discuss.elastic.co/ elastic的官方社区论坛,产品经理和研发工程师每天会在论坛上回答客户的各种疑难杂症
- https://elasticstack.blog.csdn.net/?type=blog elastic社区布道师高频发布的各种入门教程与最佳实践
- https://elasticsearch.cn/slides/ elasticsearch中文社区的社区meetup活动中,每个讲师的分享内容
在现在的elastic search platform的企业搜索解决方案中,App search应用已经包含了web网络爬虫的应用程序,我们可以在App search中快速创建Web crawler。
这里有一个基础概念:引擎。这是App search里的数据单元,反映在elasticsearch上就是一个包含可搜索数据的索引和一系列相关的元数据索引。通俗点,我们也可以理解为数据库里的有固定数据源的数据表。对应与我们日常的数据导入方式,这里提供了网络爬虫,上传JSON,以及从API写入数据三种方式:
为了获取网络上的这些资源,我们需要定义一个网络爬虫,帮助我们定期获取这些资源的内容更新,并且提供和查询的方式。
因为每个数据源会是一个单独的引擎,因此我们需要分别创建:
在创建引擎时,可以针对不同的源选择不同的引擎语言,对应的,后端在处理时会使用合适的分词器进行分词。这是我们选择以网络爬虫的方式进行数据获取,并且配置入口点(完整的url),爬虫会从入口点推断出域(domain),需要注意目前提供的傻瓜式爬虫不支持跨域爬取,其功能主要是提供一个网站内资源的扫描,作为快速构建网站导航搜索的解决方案的核心功能。
针对每个被爬取的网站,Elastic App search中提供的web crawler会严格遵守网站具体的robots.txt中声明的爬虫规范,只爬取被允许的扫描的path。
创建爬虫后,我们需要配置爬网规则。我们以elastic中文社区(https://elasticsearch.cn/)为例,我们只希望获取社区讲师分享的精品内容:
该内容主要在 https://elasticsearch.cn/slides/ 路径下。而对于其他内容,比如论坛的问答:
主要是在/questions、以及/articles等路径下。因此,我们需要通过爬网规则过滤我们不需要的内容:
这里通过配置只允许爬取路径包含/slides/[0-9]{1-5}
的方式来进行过滤,比如:https://elasticsearch.cn/slides/290。
而对于其他的,一律不允许(Regex: .*
)。图中我们配置了多条规则,elastic web crawler的工作方式是按顺序从上到下进行规则匹配,直到匹配上一条规则,然后break。
点击开始爬网后,爬虫会定期爬取网页与更新,并且在elasticSAErch中记录状态和日志。
使用Fscrawler扫描本地的文件资源
相对于使用标准的、由Elastic原厂提供的web爬虫爬取的网络资源,Elastic原厂尚未提供针对本地文件系统上的资源的连接器,因此还需要依赖一些开源社区提供的工具。这里推荐的是Fscrawler。
Fscrawler是由Elastic的员工开源和维护的一个Elasticsearch的 文件系统爬虫工具。其功能包括:
在这里,我们主要用到的是本地文件系统爬虫的功能。该工具上手非常简易,只需要把应用程序下载到本地,启动的时候提供一个任务名,比如这里的job_name
:
bin/fscrawler job_name
18:28:58,174 WARN [f.p.e.c.f.FsCrawler] job [job_name] does not exist
18:28:58,177 INFO [f.p.e.c.f.FsCrawler] Do you want to create it (Y/N)?
y
18:29:05,711 INFO [f.p.e.c.f.FsCrawler] Settings have been created in [~/.fscrawler/job_name/_settings.yaml]. Please review and edit before relaunch
fscrawler会自动创建一个文件抓取任务的配置文件,保存在~/.fscrawler/job_name/_settings.yaml
,我们只需要在_settings.yaml文件中提供关键信息即可,例如:
---
name: "elastic"
fs:
url: "/Users/lex.li/Documents/elastic/"
update_rate: "15m"
excludes:
- "*/~*"
- "*.py"
- "*.zip"
- "*.js"
- "ds_store"
- "pyc"
- "console"
json_support: false
filename_as_id: false
add_filesize: true
remove_deleted: false
add_as_inner_object: false
store_source: false
index_content: true
attributes_support: false
raw_Metadata: false
xml_support: false
index_folders: false
lang_detect: false
continue_on_error: false
ocr:
language: "eng"
enabled: true
pdf_strategy: "ocr_and_text"
follow_symlinks: false
elasticsearch:
username: "elastic"
password: "your-password"
nodes:
- url: "https://lex-demo.es.ap-east-1.aws.elastic-cloud.com"
bulk_size: 100
flush_interval: "5s"
byte_size: "10mb"
这里,我扫描的是本地目录/Users/lex.li/Documents/elastic/
,过滤了我不需要的文件:
excludes:
- "*/~*"
- "*.py"
- "*.zip"
- "*.js"
- "ds_store"
- "pyc"
- "console"
并且指定了我的后端Elasticsearch的信息:
elasticsearch:
username: "elastic"
password: "your-password"
nodes:
- url: "https://lex-demo.es.ap-east-1.aws.elastic-cloud.com"
bulk_size: 100
flush_interval: "5s"
byte_size: "10mb"
扫描之后的文件信息,会在Elasticsearch中创建一个跟任务同名的信息,并且包含检索信息所需要的所有字段,比如:content
、file.filename
、file.extension
、file.url
、file.filesize
等。
我们可以用同样的方式,将本地的官方文档,同样作为一个数据源,添加进来,只需要把本地的官方文档的目录,作为一个新的fscrawler的任务进行一次性的扫描即可。获取离线文档的方式可以参考博文:Elasticsearch进阶教程:生成离线官方文档
数据源的整合
到目前位置,我们已经分别创建了好几个数据源:
每个引擎就是一个单独的一个数据集,当通过UI来进行检索时,通常是引擎之间是相互隔离的。但我们希望针对某个主题做更广泛的搜索的时候就需要跨数据源的检索,这时就需要元引擎。
什么是元引擎
元引擎是没有自己的文档的引擎。相反,它结合了多个其他引擎,以便可以将它们一起搜索,就好像它们是单个引擎一样。
构成元引擎的引擎称为源引擎。
示例:可以将两个引擎“western-national-parks”和“eastern-national-parks”组合在一个名为“national-parks”的元引擎中,以便将它们作为一个数据集进行搜索。
GET <ENTERPRISE_SEARCH_BASE_URL>/api/as/v1/engines/parks/search
{
"results": [
{
"id": "eastern-national-parks|park_shenandoah",
"_Meta": {
"id": "park_shenandoah",
"engine": "eastern-national-parks"
}
},
{
"id": "western-national-parks|park_yosemite",
"_Meta": {
"id": "park_yosemite",
"engine": "western-national-parks"
}
}
]
}
构建方便易用的搜索应用UI
App search最吸引人的能力之一,就是方便我们快速的构建搜索的体验。当我们创建引擎之后,就可以在界面上创建搜索UI。整个过程非常的简单,这里提供了用于筛选和排序的字段,以及点击搜索结果后的跳转链接字段(URL字段):
你也可以完全都不选择,直接点击生成搜索体验。即可在弹出的窗口上快速体验搜索的UI
如果这个UI觉得还OK,只需要点击右上角的 Download ZIP package 即可获取这个UI的源码,
解压之后,目录如下:
my-documents-react-demo-ui$ tree -L 1
.
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── bin
├── logo-app-search.png
├── node_modules
├── package-lock.json
├── package.json
├── public
├── scripts
└── src
根据压缩包里提供的README.md
, 可以快速的在本地拉起一个搜索应用:
# Run the `cd` command to change the current directory to the
# location of your downloaded Reference UI. Replace the path
# below with the actual path of your project.
cd ~/Downloads/app-search-reference-ui
# Run this to set everything up
npm install
# Run this to start your application and open it up in a new browser window
npm start
或者是参考src中的代码App.js
,将UI嵌入到自己的应用当:
└── src
├── App.js
├── config
└── index.js
这里提供了一个操作视频:
用户行为分析和相关性调优
- 用户在搜什么,什么话题最热?
- 我们提供的搜索结果里面:
- 我们如何调整搜索的准确性和相关性?
- 我们如何调整结果的排序?
- 我们如何设置同义词?比如,obersavability = o11y, kubernetes = k8s?
对于以上需求,App search已经为我们提供了开箱即用的功能:
我们如何调整搜索的准确性和相关性?
我们如何调整结果的排序?
我们如何设置同义词?
总结
通过本文我们可以看到,要构建一个涵盖互联网上内容与本地内容的定制化的知识搜索引擎,在缺乏解决方案协助的情况下,我们可能需要耗费大量的时间、精力、人力去进行设计、开发和维护。而使用Elastic Search platform,我们可以在一天之内完成这个项目的构建,不仅大量节约了时间,从效果上,更能帮助我们打通获取知识道路上的壁垒