啥?还要单独讲一下啥是搜索引擎?不就是百度、Google嘛,这玩意天天用,还轮的到你来说?
额,好吧,虽然大家天天都在用,但是我发现,其实很多人对搜索引擎并不是特别了解,更别提搜索引擎开发了。不信?那么咱们就一步一步来看。
上来先官方,看看百科中对搜索引擎的定义。
搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上采集信息,在对信息进行组织和处理后,为用户提供检索服务,将检索的相关信息展示给用户的系统。搜索引擎是工作于互联网上的一门检索技术,它指在提高人们获取搜集信息的速度,为人们提供更好的网络使用环境。从功能和原理上搜索引擎大致被分为全文搜索引擎、元搜索引擎、垂直搜索引擎和目录搜索引擎等四大类。
嗯,一堆没啥用的概念。但我们能从中看到,搜索引擎是根据策略,也就是根据我们的搜索关键词,以最快的速度返回匹配度最高的信息。然后包括全文检索、垂直搜索这两个重要的类型,我们日常开发中,需要开发的也正是这类搜索引擎。
通常来说,在数据库中,如果数据量不大,其实通过 like 就可以实现模糊匹配。这就是一种搜索实现,只不过,like 如果是前后都有 % 的,就走不了索引,数据库引擎需要对每一条数据的每一个字段里面的内容进行全部的单词匹配。如果数据量大了,那么效果可想而知。特别是如果是针对大型的文章、文献,本身字段的内容也非常长,这样匹配就更费劲了。
而搜索引擎,一般会采用倒排索引,能够大大提升词组的匹配效率,进而提升查询速度。关于倒排索引的概念我们会在后面再说。
既然提到了倒排索引,那么就要牵涉出另一个词汇,那就是分词。很多人会把搜索引擎的搜索功能和 like 混淆,这一点一定要搞清楚,如果不搞清楚,就会出现一个很大的误区。划重点了,分词+倒排索引,和 like 匹配,完全不是一个东西。
在学习搜索引擎开发前,我们需要了解一些概念性的内容。
索引:搜索引擎中的索引只有一个,那就是倒排索引。后面的文章我们会详细的说明。搜索引擎在开始使用的时候,一定都有一个建立索引的过程。
分词:针对文档内容,以及查询语句,我们要将它们进行分词,如果不分词,就无法快速建立倒排索引。同时,中文分词又是非常重要的内容。
引擎:百度、Google的强大引擎不提,我们日常开发中用到的主要就是 Lucene 系列的,如 ElasticSearch、Solr 等,另外还有 Sphinx 使用的基于 SQL 的搜索引擎以及我们的主角 XunSearch 所使用的 Xapian 引擎。
排序/评分:我们查询了数据之后,数据是按什么顺序返回的呢?如果是数据库,可能会指定一个排序字段,但搜索引擎一般会根据相关性评分进行排序,也就是说,我们应该搜索到的是最贴近搜索词的内容,一般也是用户最想看到的内容。
标点符号:基本上所有的搜索引擎都会过滤掉标点符号,最开始我还在纠结为什么我单独来个问号搜索不到内容,其实呀,搜索引擎就是为了做语义词组搜索的,标点符号在大部分情况下是没有太多意义的呀。当然,百度上面是有意义的,但咱们不能跟他比。
虽说不全面,但上面几点内容应该是比较重要的方面。其中索引、分词、排序、评分等内容我们后面还会有更详细的学习。今天我们先来了解一下引擎和框架。
XunSearch 中文名是 迅搜 ,国人大佬开发,提供完整的 PHP SDK 组件。
不是说好了是学习 XunSearch 嘛?Xapian 是什么鬼?这个呀,其实用 ElasticSearch 和 Lucene 来解释就很清楚了。要说搜索引擎组件中的老大,ElasticSearch 可谓是一骑绝尘。如果你之前学习过 ES 相关的内容,那么 XS (后面我们就都用 XS 来指代 XunSearch 啦,就和 ES 一样)的内容学习就非常轻松了。如果你没有学习过 ES ,那也没关系,但希望你学习完我的 XS 系列之后,再去好好学习一下 ES ,因为有些东西 XS 真的是没有的,而且有些有的东西和 ES 也是没法比的。但搜索引擎的基本概念都是相通的,而且 XS 也有自身的优势。我们下一节也会说这些搜索引擎的选型以及优劣。
好了,话说回来。Lucene 是 Java 实现的一个搜索引擎,非常强大,也非常出名,但是呢,不好用。就是比较偏底层,就像是一个 JDK 或者说是原生写法去开发 PHP 应用。而 ES 则是构建在 Lucene 之上的,提供了各种方便使用的功能以及强大的 RESTFul 接口,能够方便地使用,就像是 Java 语言或者说是使用框架来开发 PHP 应用。Lucene 和 ES 的作者是同一个人。
同理,Xapian 正是我们 XS 的底层框架,XS 是建立在其之上的,通过封装提供了现成的 PHP SDK 能够让我们非常方便地使用。除了 Xapian 之外,XS 还一道封装好了 hightman 大佬开发的中文 SCWS 分词器。相当于一个 XS 就是 Xapina+SCWS+PHP SDK 的组合。是的,你没猜错,XS 也是 hightman 大佬开发的,而且到现在也一直在更新,最重要的是,这是咱们国人的,面向中文的优秀搜索引擎解决方案哦,感谢大神前辈的努力和奉献。
那么 ES 上有分词器嘛?老外开发的肯定是英文分词没问题啦。如果要使用中文的话,需要自己安装 IK 分词器或者其它分词器插件,不过 ES 的插件安装非常简单,其实也没啥难度。这里还需要注意的是一点是,即使是英文,所有的搜索引擎也会统一以小写建立索引,也就是说,搜索引擎是不区分大小写的,统一都是小写。
好了,这下应该清楚了吧,我们要学习的核心内容都有哪些。
倒排索引、分词的概念与原理
排序、相关度评分的算法概念
XS 的使用(PHP SDK工具、PHP SDK全部功能使用等)
SCWS、Xapian 的学习
现在知道为什么上篇文章中我会说咱们这一套文章和视频可能会是全网唯一了,因为咱们不只讲 XS 的使用,还要简单地学习一下 SCWS 和 Xapian ,并且通过这些再顺道一起学习搜索引擎相关的一些基础知识。当然,重点的核心内容肯定还是 XS 的使用咯,也就是我最擅长的带着大家一起刷文档啦!
搜索引擎工具非常多,比如在 DBEngines 上,就能看到很多很多种。
ES 一骑绝尘这说法没毛病吧,所以我说,如果你之前学习过一点 ES ,那么看这个系列没啥压力,如果你没有学习过,那么学完 XS 后也最好再去看看。ES 最强大的部分在于天然分布式、性能强悍,现在也是大数据的标配了,上亿数据量轻松拿捏,更重要的是,它的生态好,社区活跃,这一点很重要。
除了 ES 之外,我略微了解过的还有 Solr 和 Sphinx ,其它的就不太清楚了。因此,我就主要对比这四个,大部分资料也是网上找到的。
XunSearch | ElasticSearch | Solr | Sphinx | |
---|---|---|---|---|
引擎 | Xapian | Lucene | Lucene | 不知道 |
引擎开发语言 | C/C++ | Java | Java | C/C++ |
应用语言 | PHP(Xapian支持各种语言SDK,因此其实 XS 也支持各种语言) | 各种语言 | 各种语言 | 各种语言 |
搜索功能支持 | 1.全文 2.搜索建议 3.分面 4.拼音搜索 5.突出显示 6.权重微调 7.拼写检查/纠错 8.突出显示 | 1.全文 2.自动完成建议 3.分面 4.多场 5.同义词 6.模糊 7.地理空间 | 1.全文 2.自动完成建议 3.分面 4.多字段 5.同义词 6.模糊 7.突出显示 8.地理空间 9.拼写检查 | 1. 全文 2. 自动完成建议 3. 分面 4. 多字段 5. 同义词(称为字形) 6. 地理空间 7. 突出显示(称为片段) 8. 拼写检查(称为qsuggest) |
扩展与分布式 | 支持主从复制 | 天然分布式 | 支持分布式 | 支持主从复制 |
查询效率 | 中等 | 高,数据量越大,分布分片节点越多,与其它相比性能就越好 | 高 | 非常高,单索引亿级也能快速搜索 |
增量索引 | 支持 | 支持 | 支持 | 增量支持度一般,但全量MySQL生成索引非常快,与MySQL等配合紧密 |
中文支持 | 自带SCWS | IK、Jieba等 | 安装第三方分词器 | 安装第三方分词器 |
资源占用 | 低 | 高 | 高 | 中 |
数据量级 | 单索引百万 | 单索引单节点千万,分布式多节点多分片没上限 | 单索引单节点千万,分布式多节点没上限 | 单索引亿级 |
开发友好 | 极高,对我们 PHPer 来说当然是极高了,而且确实简单 | 高 | 高 | 高 |
好了,这些对比是不是客观全面我也不知道,反正也是网络上收集来的,不过大部分的对比文章都会提到这些。我们再拿 XS 和 ES 来总结一下,因为我更推荐的,就是只学这两个就可以了。
XS:简单好上手,中文分词友好,国人开发,文档齐备,部署方便,快速上线。唯一缺憾,没有地理空间索引,O2O相关的项目就不要考虑了。
ES:强大,排名无人可匹敌,天然分布式支持,能玩大数据的,知识体系更为庞大,除了搜索之外还有聚合计算以及分析能力,生态健全也更活跃。
为什么只推荐学习这两个呢?
第一,PHPer 们大部分接触到的项目,说实话,XS 完全足够。
第二,如果确实有很大的数据量,直接用最热门的,准没错。
第三,XS 上手简单,学习应用速度快,和 PHP 无缝对接,分分钟上线功能。
第四,ES 代表着最先进,所有的知识、插件、概念都比较新,功能齐全。
第五,搜索引擎的基础知识和原理是相通的,就像数据库的原理一样,需要使用其它的学习也很快。
怎么感觉说完这一节,更想去学 ES 了,哈哈哈哈!
好吧,咱们还是要以 XS 为主哦,不过在学习过程中,我们在需要做对比的时候,也会直接使用 ES 来进行对比。比如马上我们就会说一下问题。
上一篇文章中,我们搭起了应用环境,也插入了一些测试数据,不知道大家有没有测试给出的那些查询语句的结果。其中有一条是这样的。
> php vendor/hightman/xunsearch/util/Quest.php demo 项
小伙伴们测了没?是不是查不出东西呀!
跟你说,查不出来就对了,用 ES 也查不出来。如果你学过 ES ,那么在 Kibana 中使用下面的 ES 命令建立索引并插入数据来进行测试。(如果没学过的话就等视频哈,在视频里我也会演示)
PUT demo
{
"mappings": {
"properties": {
"pid":{
"type":"integer"
},
"subject":{
"type":"text",
"analyzer": "ik_max_word"
},
"message":{
"type":"text",
"analyzer": "ik_max_word"
},
"chrono":{
"type":"integer"
}
}
}
}
POST demo/_doc
{
"pid":1,
"subject":"关于 xunsearch 的 DEMO 项目测试",
"message":"项目测试是一个很有意思的行为!",
"chrono":1314336158
}
POST demo/_doc
{
"pid":2,
"subject":"测试第二篇",
"message":"这里是第二篇文章的内容",
"chrono":1314336160
}
POST demo/_doc
{
"pid":3,
"subject":"项目测试第三篇",
"message":"俗话说,无三不成礼,所以就有了第三篇",
"chrono":1314336168
}
第一个 mappings 就是 ES 中的索引映射,就相当于表结构。我们针对 subject 和 message 使用了 IK 分词器来作为分词器。在 XS 中我们没有这个呀?不不不,有的,我们后面会看到,XS 自带的测试 demo 的结构就是和这个一样的。然后插入同样的三条数据。接下来进行查询测试。
GET demo/_search
{
"query":{
"query_string" : {
"query" :"项目"
}
}
}
GET demo/_search
{
"query":{
"query_string" : {
"query" :"项"
}
}
}
不出意外的话,第一个查询和我们在 XS 中的查询结果是一样的,第二条则也同样查不到任何数据。
为什么呢?因为分词,重点说三遍,分词分词分词,索引索引索引。“项”按正常的分词器,不管是 IK 还是 SCWS ,都不会当成一个单词,也就不会为它建立倒排索引,这样就无法查询到。
而 like 语句的原理,是针对字段里的值逐一匹配,ES 中有类似的 wildcard 功能,但如果数据量非常大的情况下,使用 非前缀匹配的 wildcard 也会同样带来性能问题,因为它就和 MySQL 中使用 like 一样了,没法用到索引。XS 中没有类似的功能,XS 是完全的全文分词检索。
为啥要单独说这个?因为很多人,在迅搜的官网以及 Github 的 issue 中,都会不分青红皂白的上来就是说搜得不准,啥都搜不出来什么的。说实话,没有系统学习搜索引擎相关的知识前,我也不知道,我也以为它就是和 like 一样。为啥一个“项”字就搜不出来东西了?真是垃圾。
照这么说的话,ES 可能也得划到垃圾的范围中了。那么可以像类似于 like 一样去搜索吗?可以,但是不推荐,等到后面学习分词相关的知识时,我们会回来解决这个问题。
今天,我们先抛出问题,接下来的文章中咱们就一一学习全文检索、倒排索引、分词、文档、词频排序等等这一大堆的概念。
今天的内容还好吧,比较概念,后面也还有一篇概念性的内容,主要就是倒排索引和分词的概念。完了之后才会开始正式的 XS 的应用学习,并在其中再穿插其它概念性的内容。没办法,我也想直接全部都在 XS 的学习过程中穿插概念性的内容,但是在搜索引擎中,索引和分词的概念确实是要提前说明的,就像上面的例子一样,否则大家就会一直在疑惑为啥总是搜索不到想要的东西。
不过反过来说,概念掌握了之后,其实不管是 XS 还是 ES ,或者其它任何搜索引擎工具,那都只是形式上的不同而已了。学习,在道、法、术三个层次中,最终要掌握的还是道,法是经验的积累,而术真的只是照着文档敲的事了。
另外做个小约定,从今天开始,全部使用 XunSearch 的简称 XS 了哦,有的地方可能我也会用中文名称 迅搜 ,但不再打完整的 XunSearch 这个词了哦。同样的,在需要对比的地方,我也会用 ES 来表示 ElasticSearch 。