数据二三事 搜索

数据二三事 搜索


提到搜索,我们先讲一个和搜索相类似的名词"查询"。当然在不同领域内,他们的定义不尽相同,在我们的业务领域他们有什么区别呢,我们来想一下我们整个业务的发展,信息化建设一开始主要提供的是查询的服务。在没有信息整合的时期,我们实现的是对单类信息的查询,而且在查询时我们也是明确数据项的。大家最常见的是系统界面会有多个表单,比如你要查的是人口信息,那么有姓名的表单,性别的表单、民族的表单,你提供查询请求后,系统会按照系统界面中的对应关系去后台数据库中去查询相应的结果,在这里查询后端的数据库大多也是关系型数据库。大家知道关系型数据库存储的是结构化数据,所以我大致理解查询就是基于结构化数据的查询。而且大多数查询是知道查询项的,比如查"张三",一般明确的就是查姓名这个数据项。


在这里提一下"索引"这个术语,索引在一般场景里指将书刊中的内容分类摘录,表明页数,按一定次序排列的一种工具。而在数据库场景中索引是一种单独的、物理的对数据库中一列或多列的值进行排序的一种存储结构。举例来说,书刊的例子如字典里的按汉字笔画查字这个工具,它就是笔画索引。我们数出"二"这个字有两笔,然后就可以去笔画索引那里去找两笔的字,然后找到"二"后就可以找到"二"所在的字典页码了。


数据二三事 搜索


同样的在数据库中索引实现的原理也是一样的。比如我们有年龄这么一个字段,我们就可以按照年龄大小进行排序,然后构造年龄这个字段的索引。当我们查询一个年龄为45岁的人时,数据库会先去查年龄的索引,然后找到45岁所对应的的数据位置。可以看出索引的引入会大大加快数据查询的速度,如果没有索引,原则上你查一个年龄为45岁的人,后台数据库会进行全表扫描,逐条匹配,这样的话不仅速度慢而且浪费了大量的数据库性能。


简单加上索引的关系数据库查询在业务前期满足了我们基本的信息查询需求,但随着业务的发展、数据的融合、需求的深入,只是简单的查询已经远远不能满足我们的实战需求,比如我们要查"张某三"、或者我们不确定"张三"就是姓名还是别的什么信息,更有甚者,我们想查"张三盗窃"这事有没有。


这些需求我们原有的关系数据库查询就很难响应了,尽管可以做相关的改造和适配,但代价太大。其实在这里我们的需求就不仅仅是查询了,而是搜索的需求。我认为搜索与查询最大的区别就是查询非结构化数据的能力,搜索是能对非结构化数据进行处理的,就例如搜索"张三盗窃"这个信息。


这种能够对非结构化数据(主要是文本数据)进行搜索的技术业界叫做全文检索、全文检索可以实现对非结构化数据的全文检索功能。目前市面的百度、谷歌也是采用的这种技术。那么全文检索是怎么实现这样的功能的呢?


还是引入一个术语"倒排索引",为啥叫倒排索引?倒排索引和我们上文所提到的关系数据库中的索引是不同的,因为它索引的方式和普通索引相比是转置的,所以叫倒排索引。


还是举例说明吧,不知道大家玩没玩过诗词的"飞花令",也就是前段时间大火的中国诗词大会节目的一个项目。


数据二三事 搜索


比如出一个字"前",让你背出所有带"前"的诗句。这个其实有些难度,即使你会背很多诗词,很多诗词里面有"前"这个词,但你一时却很难想起。这是为什么呢,原因就在于你的大脑中没有建立"倒排索引"。你大脑中建立的都是正向的索引,比如我提示你说"静夜思,李白",你立即就能说出来"床前明月光"了。你的大脑中存有这个诗句,它的记忆方式如下图:


数据二三事 搜索


可以看出,这是一个正向的索引,也就是从文档到细化的信息,但你正向的索引是无法完成"飞花令"这个任务的。


那么倒排索引是怎样的呢,倒排索引就是拿细化的信息去索引整个文档,在这里就是拿具体的字词去索引诗句了,也就是如下图:


数据二三事 搜索

这样的话我们就能轻松的由"前"这个索引找到对应的诗句了。


我们可以继续维护这个索引,比如"日照香炉生紫烟,遥看瀑布挂前川"里面就有"前"字,我们就把这个诗句也加到这个索引上去。这样的诗句会越来越多,我们就建立了一个从文档中字词"前"到整个文档《静夜思》、《望庐山瀑布》的索引,这就叫倒排索引,好理解了吧。


当然如果你想背带有"月"字的诗句,那么也要建立"月"字的倒排索引。在往上,如果你想背带有"明月"的诗句,那么建立"明月"的倒排索引。这里就有个问题,怎么建立"明月"这个索引呢,我们知道"明月"是个有意义的词语,所以我们得把"明月"看做一个整体,把"明月"从原诗句中提取出来,那么我们就需要对原来的文档做分词处理。


分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。我们知道,在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符,虽然英文也同样存在短语的划分问题,不过在词这一层上,中文比之英文要复杂得多、困难得多。分词细研究下去知识很多在这里不谈。


我们继续。


如果要求背既带"前"字又带"月"字的诗句呢。如果我们分别建立了"前"字和"月"字的倒排索引,


数据二三事 搜索

数据二三事 搜索


从图中看,"前"字索引到了三个文档诗句,"月"字也索引到了三个文档诗句。如果我们要背既带"前"字又带"月"字的诗句,那么只需要将上面的值做一下交集,就能找出来"床前明月光"这句诗了。


到这里基本的原理就可以用"飞花令"简单的描述清楚了。我们回过来看我们的业务需求,像搜索"张三",我们就可以将后台数据项都进行倒排索引,这样当前台输入"张三"时,后台进行索引匹配,不管索引到那条数据的那个字段,都可以给你搜索出来,哪怕是一段案情描述中出现了"张三"这个词。


再如搜索"张三盗窃",前端在收到"张三盗窃"这个搜索词后,会先进行分词操作,也就是把"张三盗窃"分成"张三"和"盗窃"两个词,然后分别去倒排索引中去寻找对应的数据。然后把"张三"匹配到的所有数据记录和"盗窃"匹配到的数据记录做交集,最终找到包含"张三盗窃"信息的数据。当然在这里,"张三盗窃"可以是不连续的词语。这样就牵扯到匹配精确度的问题,比如"张三"和"盗窃"两词挨在一起的我们认为匹配最精确,"张三"和"盗窃"两词不挨在一起的稍弱一些,这些我们都可以设置。所以我们能看出,处理非结构化数据的全文检索(搜索)的结果也和结构化数据的查询是不一样,搜索的结果是精确度匹配,是按照数据对请求匹配程度来响应的,而查询一般就是精确匹配,是就是,不是就是不是。


现在流行的提供全文检索能力的工具有elasticsearch,它提供了倒排索引、分词等等的能力,现在许多的搜索类系统都在采用elasticsearch。有机会再跟大家详细聊一聊elasticsearch,但现在还没怎么学习。


数据二三事 搜索


分享到:


相關文章: