一、前言
在日常生活中我们常常用到搜索功能,不管是专业的搜索引擎百度,谷歌还是各类APP内嵌的搜索功能。搜索本质上是用户和搜索引擎之间的一种人机对话,用户通过为搜索引擎提供合适查询条件,以满足其信息需求,搜索引擎利用这些查询条件和定制化规则,给用户返回期望的相关性内容。作为一个初阶的搜索PM,本文意在以相对通俗的语言讲解搜索的工作原理,欢迎拍砖。
全文较长,以下为整体流程图:
二、搜索引擎概述
2.1什么是全文搜索引擎
百度百科的定义为:全文搜索引擎是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。
对于像我们这样的初学者,往往对搜索引擎的实现方式抱有极大的误解,一方面觉得搜索就是一个黑盒,搜索效果极难把控,另一方面又觉得搜索技术相对复杂,对于其原理难以理解。其实搜索在本质上依然是机械的词匹配(term-matching),大量复杂的其他环节均是为了保证该环节的准确高效,后面将会详细讲述搜索引擎工作的整个过程
2.2什么情况下需要搜索引擎
对于少量结构化数据而言,数据库(如 Oracle、SQL Server )已经可以实现查询检索或者聚类分析功能,但对于非结构化数据,或者数据量级较大的情况时,就需要搜索引擎的帮助了,以下是从网上摘录的需要搜索引擎的几种触发条件,这里不做讨论。
1、搜索的数据对象是大量的非结构化的文本数据。
2、文件记录量达到数十万或数百万个甚至更多。
3、支持大量基于交互式文本的查询。
4、需求非常灵活的全文搜索查询。
5、对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
6、对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。
2.3常见的搜索引擎介绍
现在主流的搜索引擎大概就是:Lucene,Solr,ElasticSearch这三种
Lucene是一个Java全文搜索引擎,完全用Java编写。需要注意的是Lucene不是一个完整的应用程序,而是一个代码库和API,可以很容易地用于向应用程序添加搜索功能
Apache Solr是一个基于名为Lucene的Java库构建的开源搜索平台。它以用户友好的方式提供Apache Lucene的搜索功能。作为一个行业参与者近十年,它是一个成熟的产品,拥有强大而广泛的用户社区。它提供分布式索引,复制,负载平衡查询以及自动故障转移和恢复。
Elasticsearch是在Solr之后几年推出的。它提供了一个分布式,多租户能力的全文搜索引擎,支持多种语言,更加友好,可以理解为在Lucene基础上进行了二次封装。
2.4常见的搜索引擎对比
虽然solr和ES 本质上都是基于Lucene的,但由于Lucene的复杂性,除了一些公司需要自研搜索框架,底层需要依赖Lucene外,一般很少会考虑它作为搜索的第一选择,
对于solr和ES ,在综合考虑实现成本和易用性后,个人觉得 ElasticSearch较为出色。(当然如果公司现在已经是solr了 并没有迁移的必要)
2.5搜索专有名词讲解
为了更好地理解搜索引擎工作的原理,我们先讲解几个搜索相关的名词
1、Index:索引,由很多的 Document 组成,是搜索引擎的核心,可以粗暴的理解为一种特定的存储数据方式
2、Document:文档,是搜索的核心,搜索、存储、返回的都是文档,它由很多的 Field 组成,是索引和搜索的最小单位。
3、Field:字段,由很多的 Term 组成,包括 Field Name和 Field Value。
4、Segment:段,可以理解为一个子索引,添加索引时并不是每个 document 都马上添加到同一个索引文件,它们首先被写入到不同的小文件,然后再合并成一个大索引文件,这里每个小文件都是一个 segment。
5、Term:由很多的字节组成。分词之后的每个最小单元叫做 Term。
6、Token:Token 是 term 的一次出现,它包含 term 文本和相应的起止偏移,以及一个类型字符串。一句话中可以出现多次相同的词语,它们都用同一个 term 表示,但是用不同的 Token,每个 Token 标记该词语出现的地方。
三、搜索引擎的工作流程
想要搜索引擎正常工作可以粗暴的分为两个环节,第一个为内容的处理过程,相当于准备工作。第二环节个为 接收到用户的query请求后的处理过程。
3.1对内容进行索引处理
将数据存储进数据存储的过程中需要信息的提取(extract)、转换(transform)和加载(load)过程,通常缩写成ETL,搜索引擎把目标数据按照特定的格式存储的过程依然符合这个流程。如下图所示,这些环节包含提取、充实、分析和索引。下面分环节讲解
3.11提取-将内容提取为文档
文档,是搜索的核心,搜索、存储、返回的其实都是文档,搜索的数据来源有很多,理想的情况我们所需要的数据被规整的存储在我们的数据库中,这种情况比较简单,按照流程提取即可。复杂一点的情况我们的数据来源于互联网或者其他地方,我们就需要进行额外的处理(清洗,识别)。该环节的最终目的是将搜索数据处理后以文档的形式发送给搜索引擎
3.12充实-清理、强化、合并文档
文档充实包括三大部分:清洗数据、强化数据、以及合并外部数据。
清洗:清洗数据这一条最好理解,为了获得一流的搜索体验,我们事先需要对已经转换成文档的数据进行一些诸如拼写错误之类的处理。
强化:这一环节意在对文档进行一些比清洗更高级的处理,提取出一些有用的特征,例如利用机器学习对文档进行分类或聚类,或者利用情感分析&语义识别来确定一篇文章的主旨和其他特征,这一环节在后续的排序等环节都有巨大的裨益,具有较大的操作空间
合并:这里指的合并并不是指文档之间的合并,而是指将一些新的标准化的数据合并到文档中,比如来自不同数据库之间的数据字段的缺失补全(eg:产地、国家)
3.13分析-字符过滤、分词处理、token过滤
当搜索数据从各地转换成标准的“文档”后,将会进行分析环节,在这个环节搜索引擎将会把文档数据转换成token,存储于搜索内部供下一步索引所用。这个环节同样分为三步:字符过滤、分词处理、token过滤
字符过滤:利用字符过滤器,过滤掉多余的格式和字符,这个环节可根据实际需要做任何处理,如果有需要还可以用正则表达式或者建立自己的字符过滤器
分词处理:顾名思义,分词就是将原生文本分词成一个个独立的token,最简单的分词方法就是利用空格和标点符号进行标准分词,当然这种时候大部分效果都不太好,可以尝试着用国内比较流行的中文分词工具,如jieba、SnowNLP、THULAC、NLPIR。分词是影响搜索结果的一个重要环节,为了保证分词的准确性我们需要进行许多工作(核心词、知识图谱、语义识别等等),这里不做展开。
token 过滤:该部与字符过滤器的功能类似,通过对token的添加删除&修改,对token流进行调整,本质上都是对元数据的标准化处理
3.14索引-倒排索引
划重点,倒排索引(inverted index)是搜索的精髓,重中之重!需要重点理解
倒排索引由两部分组成:词典和倒排表。词典是制定字段在一个文档集合中出现的所有词汇所组成的有序列表。词典中的每一个词都有一个包含该词的文档ID与之对应。为了更好地理解,我们举个例子:
文档:
0:one shoe,two shoe,the red shoe,the blue shoe.
1: the blue dress shoe is the best shoe
2: the best dress is the one red dress
词典:
best:0 blue:1 dress:2 is:3 one:4 red:5 shoe:6 the:7 two:8
倒排表:
0:[1,2] 1:[0,1]
2:[1,2]
3:[1,2]
4:[0,2]
5:[0,2]
6:[0,1]
7:[0,1,2]
8:[0]
此时假设用户搜索red,通过词典我们知道red对应的序号为5,然后通过倒排表即可发现相关文档为0和2。以上就是倒排索引的实现方式和原理,在实际操作中,为了更好地用户体验,我们还可以利用更多的索引属性数据,如:文档频率、词频、词位置、词偏移量等等,这里不做详述
3.2召回结果并排序
3.21布尔搜索
在做完搜索的前期准备后,我们已经能实现单个词的文档搜索了,但是对于多个词的匹配,我们还需要更好地方法,即布尔搜索,布尔搜索可以合并多条查询的返回结果,从而提供更好地搜索体验。
典型的布尔操作理解和实现均较为简单:即(AND\OR\NOT),包含,有其一,完全不包含。
以lucene为例,有一种查询类型为booleanquery的函数用于实现布尔搜索,他有三个字段:SHOULD\MUST\MUST_NOT,及必须包含,选择性包含和一定不包含。通过这些子句的排列组合就可以实现简单的搜索啦~~~
3.32 query处理
该环节的意义为在用户的帮助下更好的搜索,比较简单的实例是筛选器,query纠错、同义词、近义词等,意在更好的理解用户的意图,帮助用户写出一个更精准更符合搜索逻辑的query词,以提升搜索准确性。这里也是搜索产品经理工作的重点方向,本次不作讲解了
3.33排序排名
在处理好数据、能实现简单搜索以及帮助用户处理好query后,我们就需要对得到的文档进行排名啦~在实际应用中,除了最关键的相关性部分,往往我们还需要考虑地域、商业化甚至个性化等因素综合的决定每一篇文档的排序位置,这里只考虑相关性的问题。
文档的相关性是由“排名函数”决定的,排名函数接受query和匹配文档的所有信息,并针对每一篇文档给出一个相关性得分,代表着这篇文的匹配的程度。
排名函数的基本原理是考察词频(TF)和词的重要程度(IDF),即TF-IDF,通俗的理解为搜索词在对应的文档中出现的次数越多,得分越高,此为词频,词越短出现次数越少,则越重要此为逆文本频率指数。这两项想乘就会得到每个query词对应文档的相关性得分,在此基础上可以再结合业务逻辑乘以相关系数(boost),来调优。
四、总结
以上就是搜索的整个工作流程和原理了。搜索是提高APP信息获取效率的重要方式,以上只是粗浅的理解整个过程,实际上每个环节都有很多很复杂的工作要做,作为一个初级搜索产品经理,要学习的东西还有很多~~共勉~
资料引用:
《相关性搜索》-Doug Turnbull John Berryman
《这就是搜索引擎:核心技术详解》
https://www.cnblogs.com/jajian/p/9801154.html
https://www.cnblogs.com/dreamroute/p/8484457.html