如我们在1.1.1节中所提到的那样,这些讨论只是一种指南性质的建议,不要把它们当成严格的使用规则来看。在我们开始之前,你需要意识到想做出一个优秀的搜索服务,其门槛是很高的。现在的用户都习惯于使用像Google和Bing这样又快又高效的网络搜索引擎,而很多受欢迎的网站也有自己强大的搜索方案来帮助用户快速的获取想要的信息, 所以用户对搜索服务并不陌生并且会非常的挑剔。当你在评估像Solr这样的搜索引擎时,或是在设计你自己的搜索方案时,一定要有根弦儿,要把用户体验放在高优先级上来考虑。
基本的关键字查询
很明显,作为一个搜索引擎来说, 首先必须要能够支持基本的关键词查询。这也是搜索引擎的主要功能之一。不过关键词查询功能还是值得在这里强调一下的,因为这是用户使用搜索引擎最典型的方式。很少有用户想要会一上来就填写一个很完整的复杂搜索表单来进行搜索的。考虑到关键词搜索功能将会是用户和你的搜索引擎之间最常见的交互方式,这个基本功能必须能够提供给用户以非常好的用户体验才行。
一般来说,用户希望只输入几个简单的关键词就能获取到很好的搜索结果。这也许听上去像是一个简单的匹配任务:把查询字串和文档进行匹配即可。不过请考虑一下要实现良好的用户体验所必须解决的几个问题:
· 相关结果必须迅速返回,大多数情况下要求一秒钟之内就能够返回
· 用户的查询字串出现拼写错误时能够自动纠错
· 用户输入时通过自动补全建议来减少用户的输入负担,这在移动应用中很常见
· 处理查询字串中的同义词近义词
· 对包含查询字串的语言变异的文档进行匹配(译者注:语言变异是语义学术语,即用词不完全一样的近似表达)
· 短语处理,用户是希望匹配短语中所有的单词,还是只要匹配短语中的部分单词就行
· 对一些通用介词的处理,比如“a,” “an”, “of”, “the”等等
· 如果最靠前的查询结果用户不满意, 如何给用户返回更多的查询结果
就像你看到的那样,不使用特定的处理方法的话,这样一堆问题会使得看上去如此简单的功能实现起来变得很困难。然而利用像Solr这样的搜索引擎,这些功能就能立等可取,实现起来变得很简单。当你给用户提供了一个强大的关键词搜索工具之后,接下来你就需要考虑如何去展示查询的结果,这就引出了下一个用例,按照结果同查询请求之间的相关性顺序,对搜索返回的查询结果进行排序。
排序的检索结果
搜索引擎为查询返回“最靠前“的结果。在SQL查询关系型数据库的时候,某一行数据记录要么匹配查询被返回,要么不匹配查询被忽略,查询结果也是按照数据记录的某一列属性来排序的。而对于搜索引擎来说,返回的结果文档是按照得分做降序排列的,该得分表示文档和查询的匹配程度。匹配程度得分依据一系列的因子来计算,不过一般说来得分越高,表明结果文档同查询之间的相关度越高。
有好几个因素决定了将结果文档按照相关度排序的方式很重要。首先,现代搜索引擎一般都存储着海量的文档,都是上百万甚至数十亿记的。如果不对查询结果进行相关度排序,那用户就会被海量的返回结果所淹没,无法清晰有效的浏览搜索的结果。其次,用户使用其他搜索引擎的经验使得用户已经习惯于使用少数的几个关键词就能获得不错的查询结果,也使得用户普遍比较缺乏耐心。他们会期待搜索引擎按照他们想要的意思来工作,而不管其所输入的信息是否完全正确。比如对于移动应用的后台搜索服务来说,用户会期待在输入了简短的几个可能还包含有拼写错误的查询词之后,搜索服务就能够返回正确的搜索结果。
如果要人工干预排序的结果,你可以给特定的文档、值域、或者查询字串增加权重,或着直接提高某个文档的相关度分值。比如你如果希望把新加入的文档推送到最靠前的位置,就可以通过按照创建时间来提高文档排序的方式实现。我们在第三章中会学习关于文档排序的知识。
除了关键词查询之外
利用像Solr这样的搜索引擎,用户可以输入少数几个关键词就能获取到一些搜索结果。然而对于很多用户来说这仅仅是一个查询交互的第一步。他们需要在查询结果中能够继续地浏览。驱动一个信息发现的交互会话过程也是搜素引擎的一个主要应用场景。通常用户在搜索前并不是很精确的知道想要查询的信息什么样的,他们事先也不知道你的系统中到底存储了哪些信息。一个好的搜索引擎可以帮助用户不断地细化信息需求,一步步到达最需要的信息。
这里的核心思想是在返回用户最初的查询所对应的文档结果的同时,提供给用户一个工具,使其能够不断地改进查询以获得更需要的信息。换句话说,在返回匹配的文档之外,你应该返回一个工具让用户知道下一步该怎么办。举个例子,你可以对查询结果按照属性进行分类,便于用户根据需求做进一步的浏览。这种功能称之为分类检索(Faceted-Search),这也是Solr的功能亮点之一。我们会在1.2节中看到一个关于房地产的分类检索实例,在第八章中会详细介绍分类检索功能的细节。
搜索引擎不适合做的事…
最后,我们来讨论一下不适合应用搜索引擎的一些用例场景。首先,搜索引擎一般的设计是,为每个查询返回一个小的文档集,通常包含10个到100个的结果文档。更多的结果文档可以通过Solr自带的结果分页功能来获取。对于一个查询结果有好几百万个文档的情况,如果你要求所有的匹配文档都要能够一次返回,那么你会等待很长的时间。查询本身会执行的很快,但是从索引结构中重建上百万的文档绝对是一件很耗时间的事情。因为Solr这样的搜索引擎在硬盘上存储值域的方式只适用于快速生成少量的文档结果,如果需要一次生成大量的查询结果,在这种存储方式之下生成大量文档结果就会耗费大量的时间。
另一个不适合应用搜索引擎的使用场景是需要读取索引文件的大部分子集的才能完成的深度分析任务场景。即使你通过结果分页技术避免了刚刚说的那个问题,如果一次分析需要读取索引文件中的大量数据,你也会遇到很大的性能问题,因为索引文件的底层数据结构就不是为一次大量读取来设计的。
我们前面有提到过一点,但是在这里还是要再次强调一下,那就是搜索引擎技术并不适合用于在文档的相互关系之间进行查询。Solr确实是可以支持基于父子关系的查询,但是并不支持在复杂的关系型数据结构之间查询。在第三章,你会学习到如何将关系型数据结构适配到适合solr处理的扁平型文档结构中进行查询。
最后,绝大多数搜索引擎都没有直接的文档级安全支持,至少Solr是没有。如果你需要严格管理文档的权限,那你只能在搜索引擎之外来想办法。
到这里我们已经了解了适合搜索引擎处理的用例场景和数据类型,下一步该是时候讨论Solr到底能做些什么,以及这些功能是如何实现的了。在下一节中,你将学习到Solr到底有哪些主要功能,以及她是如何实现外部系统集成、可扩展性、以及高可用性等软件设计原则的。