原文:What every software engineer should know about search
作者:Max Grigorev
翻译:Diwei
译者注:想要构建或改进搜索体验?从这里开始。以下为译文。
如果你问一名软件工程师:“如何给产品添加搜索功能?”或者“如何构建一个搜索引擎?”你可能会得到这样一个回答:“我们刚刚推出了ElasticSearch集群,以后再也不用担心构建搜索功能了。”
但真的是这样吗?许多现有产品仍然 有 很不友好的 搜索 体验。很多工程师对搜索引擎的工作原理知之甚微,而这些知识往往是提高搜索质量的必要条件。
尽管有很多的开源软件包,也有了很多的研究成果,但很少有介绍关于如何构建稳定搜索体验的文章。更讽刺的是,如果在网上搜索关于搜索技能的专业,得到的结果其实并不是自己想要的。
为什么要读这篇文章?
如果你想构建搜索功能,那么这篇文章会对你提供很大的帮助。当然,并不是说这篇文章会包含所有的内容,但我们会根据读者的反馈进行修改。
由于我有谷歌、Airbnb和几家初创公司的工作经验,因此我将基于这些经验介绍一些最受欢迎的方法、算法、技术和工具。
如果你不了解搜索相关的问题有多复杂,那么产品的用户体验也肯定很糟糕,这样不仅让之前的努力付出东流,产品还很有可能会失败。
如果你缺乏耐心或者已经了解了很多知识,那么可以直接浏览工具和服务部分。
关于哲学
这篇文章很长,但我们所涵盖的大部分内容都基于下面四个基本原则:
实际上搜索是一个综合问题:
- 查询是可高度变化的。根据产品需求的不同,搜索问题也是不尽相同的。
- 想想Facebook的不同搜索方式(搜索某位用户的图表)。
- YouTube搜索(搜索个人视频)。
- 这些搜索与Kayak有哪些不同的地方(航空旅行计划真的是个很棘手的问题)。
- 谷歌地图(理解地理空间数据)。
- Pinterest。
质量、度量和流程非常重要:
- 根本就不存在什么魔法般的算法。因为流程总是在不断地促进很多技术的进化,从而满足解决各个方面的问题,并提高用户经验,通常是渐进的和持续的。
- 换句话说,搜索不仅仅只是为某个特定领域构建排名或检索(我们将在下面讨论)的软件。通常情况下搜索系统就像是一种不断变化的组件管道,随着时间的推移,它们会调整和演变,从而形成有凝聚力的体验。
- 搜索成功的关键重点是在于建立评估和调整产品和开发周期的过程。搜索系统架构师应该考虑过程和度量,而不仅仅是技术。
使用现有的技术:
- 和大多数工程问题一样,不要自己闭门造车。在可能的情况下,使用现有的服务或开源工具。如果现有的SaaS(如Algolia或托管弹性搜索)符合约束条件,而你又有足够的经济能力能够负担得起,那么也可以使用它。即使是在需要定制、增强或考虑是否需要替换的情况下,在产品初期阶段,这种解决方案也有可能是最佳选择。
即使你买了,也需要了解细节:
- 即使使用的是现有的开源或商业解决方案,你也应该对搜索问题的复杂性有一定的认识,并且需要知道哪里可能会出现陷阱。
理论:搜索问题
每款产品的搜索都不相同,而选择则需要依赖于需求的许多技术细节。它有助于识别搜索问题的关键参数:
- 大小:语料库(需要搜索的完整文档集)有多大?有成千上万个文件吗?
- 影像:用户是在搜索文本、图像、图形关系,还是地理空间数据?
- 语料库控制和质量:是你在控制的文档的来源,还是来自于(潜在的敌对)第三方?是否所有文档都准备好被索引或者需要清理和选择?
- 索引速度:需要实时索引吗?或者批量构建索引有没有问题?
- 查询语言:查询是否是结构化的,是否需要支持非结构化查询?
- 查询结构:是否是查询文本、图像、声音?还是街道地址,记录的身份证,人脸?
- 情境依赖:结果是否取决于用户是谁,他们的历史与产品,他们的地理位置,时间等?
- 建议支持:是否需要支持不完整的查询?
- 延迟:服务延迟需求是什么?100毫秒还是100秒?
- 访问控制:它是完全公开的,还是应该只看到文档的一个受限制的子集?
- 遵从性:是否有遵从性或组织限制?
- 国际化:是否需要支持具有多语言字符集或Unicode的文档?(提示:总是使用utf - 8,除非你真的知道你在做什么。)你需要支持多语种语料库吗?多语种查询呢?
通过这些点来思考,可以帮助你在设计和构建单个搜索系统组件时做出重要的选择。
![](https://i.imgur.com/dExcd9l.jpg)
生产索引管道。
理论:搜索管道
现在让我们看一遍搜索子问题列表。这些通常由形成管道的独立子系统来解决。这意味着一个给定的子系统将消耗以前子系统的输出,并为下列子系统生成输入。
这导致了生态系统的一个重要特性:一旦你改变了上游子系统的工作方式,你就需要评估变化的影响,并可能改变下游的行为。
下面是你需要解决的最重要的问题:
索引选择:
给定一组文档(例如,整个Internet,所有的Twitter帖子,Instagram上的所有图片),选择一个可能更小的文档子集,作为搜索结果可能值得考虑,并且只包括索引中的那些,丢弃其余部分。这样做是为了使索引紧凑,而且几乎是正交的,以选择要显示给用户的文档。一些特殊类别的文件没有被削减可能包括:
垃圾处理:
哦,所有不同的形状和大小的搜索垃圾邮件!一个巨大的主题本身,值得单独的指导。一个好的网络垃圾分类概述。
不受欢迎的文档:
域约束可能需要过滤:色情、非法内容等。这些技术类似于垃圾邮件过滤,可能需要额外的启发式。
重复的:
或接近重复的文件。可以通过本地敏感的散列、相似度度量、聚类技术甚至是clickthrough数据完成。一个很好的技术概述。
较低的文档:
效用的定义在很大程度上依赖于问题领域,因此很难推荐这里的方法。有些想法是:可能为您的文档构建一个实用程序函数;heuristics可能起作用,或者例如一个只包含黑色像素的图像不是一个有用的文档;实用程序可以从用户行为中学习。
索引结构:
对于大多数搜索系统,文档检索是使用反向索引执行的——通常称为索引。
所以我到底应该怎么做呢?
这篇文章并不是一篇教程,但是如果你想现在就构建一个搜索体验,这里倒是有一个简短的概述:
正如上面所说的,如果你有一定的经济基础,可以选择购买现成的SaaS(下面列举了一些评价不错的)。现有的服务适用于:
你的经验是一个“连接”一个(你的服务或应用有互联网连接)。
它是否支持您需要的所有功能?这篇文章很好地阐述了你想要什么样的功能。举几个例子,我至少要考虑一下:支持你正在搜索的媒体;实时索引支持;查询灵活性,包括上下文相关的查询。
考虑到语料库的大小和预期的QpS,你能负担得起未来12个月的费用吗?
服务是否能够支持预期的流量,在所需的延迟范围内?如果您正在从应用程序查询服务,请确保给定的服务能够快速访问您的用户所在的位置。
如果托管解决方案不适合您的需求或资源,您可能需要使用一个开源库或工具。如果有联网的应用程序或网站,我现在就选择弹性搜索。对于嵌入式体验,下面有多种工具。
- 在将文档上传到搜索索引之前,您可能需要做索引选择并清理文档(比如从HTML页面中提取相关文本)。这将降低索引的大小,并使得到好的结果更容易。如果您的语料库适合于一台机器,那么只需编写一个脚本(或者几个)来完成它。如果不是,我会用Spark。
2017年10月14日,SDCC 2017之大数据技术实战线上峰会即将召开,邀请圈内顶尖的布道师、技术专家和技术引领者,共话大数据平台构建、优化提升大数据平台的各项性能、Spark部署实践、企业流平台实践、以及实现应用大数据支持业务创新发展等核心话题,七位大牛与你相聚狂欢,详情查看所有嘉宾和议题,以及注册参会,分享还可优惠30元。