Redis还特别适用于解决基于搜索的问题,这类问题通常需要使用集合以及有序集合的交集、并集、和差集操作查找符合指定要求的元素。本章就来学习下,如何使用Redis进行搜索。假设一个对文档搜索的场景,如何使用Redis更快地进行搜索。基于搜索的应用程序相关代码位于项目的search模块中。
基本搜索原理
为了获得比扫描文档更快的搜索速度,我们需要对文档进行预处理,这个预处理步骤通常被称为建索引(indexing),而我们要创建的结构则被成为反向索引(inverted indexes)。选择使用Redis来创建反向索引的原因在于,Redis自带的集合和有序集合都非常使用于处理反向索引。
具体来说,反向索引会从每个被索引的文档里面抽取一些单词,并创建表格来记录每篇文章都包含了哪些单词。假设有两个文档,docA只包含标题《lord of the rings》,docB只包含标题《lord of the dance》。为这两个文档创建的反向索引如下:
key | set value |
---|---|
ind:lord | docA docB |
ind:of | docA docB |
ind:the | docA docB |
ind:rings | docA |
ind:dance | docB |
在知道了索引操作的最终执行结构就是产生一些Reedis集合之后,我们接下来要了解的就是生成这些集合的具体方法。
基本索引操作
为了给文档构建索引集合,首先需要对文档包含的单词进行处理。从文档里面提取单词的过程通常被称为语法分析(parsing)和标记化(tokenization),这个过程可以产生出一系列用于标识文档的标记(token),标记有时候又被称为单词(word)。为了演示简单,我们假设需要处理的文档只能由英文字母和单引号(‘)组成,并且每个字符至少有两个字符长。标记化的一个常见的步骤,就是移除内容中的非用词,非用词就是那些在文档中频繁出现但是却没有提供相应信息量的单词,对这些单词进行搜索将返回大量无用的结果。
基本搜索操作
在索引里面查找一个单词是非常容易的,通过使用Redis集合操作以及一些辅助代码,可以对文档执行各种复杂的单词查询操作。
分析并执行搜索
到目前为止,我们已经具备了建立索引和进行搜搜所需要的绝大部分工具,包括标记化函数、索引函数以及基本的交集、并集和差集计算函数。现在缺少的就是一个将文本查询语句转换成搜索操作的函数。为此,我们将实现一个搜索函数,它可以查找那些包含了所有给定单词的文档,并允许我们指定同义词以及不需要的单词。假设有这样一个查询字符串”content indexed +indexing -another”,我们要根据前缀做出不同的查询动作。不加前缀表示单纯的查找含有该单词的文档;’+’前缀表示和前面一个单词是同义词,需要求并集;”-“前缀表示需要查询不包含该单词的文档。
对搜索结果进行排序
虽然我们已经可以根据给定的单词对索引内的文档进行搜索,但这只是我们检索所需要信息的第一步。搜索程序取得多个文档后,通常还需要根据每个文档的重要性对它们进行排序。之前介绍过Redis的SORT命令可以对列表、集合或有序结合存储的内容进行排序。假设现在把文档的相关信息存储在一个散列中,数据格式如下:
- key
- kb:docA
- hash value
- subKey : id | subValue : ××××××
- subKey : created | subValue : ××××××
- subKey : updated | subValue : ××××××
如果要测试的话,这些信息自行加到redis中,下面重新定义一个含有排序功能的搜索函数。