前言
提到搭建搜索引擎,最容易想到的是使用ES(Elasticsearch),但有些时候由于资源原因某些项目有可能没有ES资源。也有可能项目太小没必要引入ES,这时大家的普遍做法还是使用关系型数据库查询代替。
现在redis已经广泛的运用于大大小小的项目,有的项目使用redis做缓存(全局共享缓存),有的项目直接代替关系型数据库用于持久层。在这些使用redis的项目中,如果没有ES资源,其实可以使用redis来实现简单的搜索引擎功能。
使用redis做搜索引擎的可行性
倒排索引
搜索引擎能保证高性能全文检索的首要因素,就是建立和使用“倒排索引”。“倒排索引”与其说是索引,不如说是一种数据结构:由“文档”中所有的“可用词”列表构成,每个“可用词”对应一个“文档”列表,这个“文档”列表中的每个文档里包含这个“可用词”。
理解起来有点绕,首先来看下上述描述中的两个术语:
文档:就是一段文本,可以是一句话,也可以是一篇文章。用文档id,唯一标识一个文档。
可用词:简单的理解就是能表示“文档”内容特征的单词,相对的还有“非可用词” 也就是在构成“文档”的辅助词。比如“我是地球人”,这里的“我”和“是”都是“非可用词”、“地球”和“地球人”是“可用词”。
换句话说:文档=可用词+非可用词。理解了这两个术语,再来看“倒排索引”的创建过程:其实就是对每个“文档”进行分词,取出该文档中的“可用词列表”,并把这个文档id放入该“可用词列表”中每个可用词对应的“集合”中。讲到这里是不是会突然想到redis的5种数据结构中的set(集合)。
分词
其实就是从“文档”中提取“可用词”列表的过程,英文的单词提取很简单以空格间隔就行。但中文不行,一般会采用一些分词工具,比如现在比较流行的Ik。但对于一个简单“搜索引擎”来说,查询关键字也许就是固定的几个单词,引入分词工具有时不是很必要。此时只需要维护一个 “公共可用词列表”即可。
引入redis
搜索引擎的关键其实就是创建“倒排索引”,前面提到“倒排索引”一般是由多个“可用词”对应的文档集合构成,在redis中巧好有set(集合)、zset(排序集合)两种数据类型可以用于存储倒排索引,由于搜索引擎一般都需要根据权重进行“复合排序”,使用zset存储更加适合。下面以一个真实的案例进行讲解,如何使用redis创建“倒排索引”。
在笔者所在的“活动页管理”系统中,需要根据“用户画像”实现“猜你喜欢”的“活动页”列表功能。“用户画像”信息(不是本主题讲解的重点)可以通过接口获得,比如“张三”的用户画像信息为:{品牌:阿迪达斯,分类:服装},用户画像信息很多 这里这是为了示例演示,只取用户喜欢的“品牌”和“分类”。其中“阿迪达斯”和“服装”就是搜索关键词。
搜索关键词有了,现在来看使用redis实现“倒排索引”的创建。在创建活动页时,一般会有活动页的基本信息,比如:活动id、活动名称、页面链接、活动描述、 “分类”、“品牌”、“更新时间”等信息。活动信息使用redis的hash进行存储(这里假设只有三个活动页):
如果要实现全文检索,一般会对“活动名称”和“活动描述”进行分词,但我们只是为了简单的复合查询,暂时不需要引入分词工具(如果要做也是可以的)。这里简单的设置三个“公共可用词”:分类、品牌、更新时间,分别对应三个redis 排序集合zset。每当一个新“活动页”被创建时会经历下列过程,以完成“倒排索引”创建。
首先创建“分类”对应的zset集合,集合的成员是页面id(文档id),分值是这个活动页的评分,主要用于排序,这个评分是通过一定算法计算出来。这里有两个分类,分别对应两个zset集合:
然后创建“品牌”对应的zset集合,成员和分值含义与“分类”集合中相同。这里有两个品牌,对应创建两个zset集合:
最后创建“更新时间”对应的zset集合,成员是页面id(文档id),分值是对应页面的更新时间。只需创建一个集合即可:
到这里“倒排索引”创建完成。
执行查询以及复合排序
现在要执行查询,查询条件就是用户画像信息:{品牌:阿迪达斯,分类:服装}(通过接口获得)。这两个条件对应redis zset集合key分别为:category_阿迪达斯、category_服装,如果希望是精准推荐其实就是对这两个集合求交集,即同时满足两个条件;如果希望是宽泛的列表推荐,对这两个集合求并集,即任意满足一个条件即可。这里假设业务方期望的是精准推荐,也就是求交集。
关于排序:业务方期望,最终的推荐结果是排序的:分值越高的活动越靠前,并且更新时间越近的越靠前。这是一个多条件的复合排序,使用redis的zset实现复合排序很简单:在zset的交集(zinterstore)和并集(zunionstore)运算结果中,会自动把两个集合的成员分值相加放到新的zset集合中,直接安装分值排序获取即可。我们认为很复杂的操作,其实在redis中一个命令就完成了,java伪代码实现如下:
public class RedisSearch { public static Jedis redis =null; public static void main(String[] args) throws Exception{ redis = new Jedis("192.168.26.128", 6379); //创建倒排索引--分类集合 redis.zadd("category_服装",8,"1000"); redis.zadd("category_服装",9,"1001"); redis.zadd("category_家电",7,"1002"); //创建倒排索引--品牌集合 redis.zadd("brand_阿迪达斯",8,"1000"); redis.zadd("brand_阿迪达斯",9,"1001"); redis.zadd("brand_海尔",7,"1002"); //创建倒排索引--修改时间集合,只推荐近一周新出的活动页,定期删除老数据,这里只需取时间搓的后6位 redis.zadd("update_time",639488,"1000"); redis.zadd("update_time",639588,"1001"); redis.zadd("update_time",639788,"1002"); //执行交集查询,对category_服装、brand_阿迪达斯、update_time求交集即可 redis.zinterstore("search_result","category_服装","brand_阿迪达斯","update_time"); Set<Tuple> first = redis.zrangeWithScores("search_result",0,-1); Iterator iterator =first.iterator(); while (iterator.hasNext()){ Tuple temp = (Tuple)iterator.next(); System.out.println("成员:"+temp.getElement()+"--"+"分值:"+temp.getScore()); } } }
执行main方法,打印信息为:
成员:1000--分值:639504.0 成员:1001--分值:639606.0
可以看到查询结果page_id分别为1000和10001,并且已经进行了“复合排序”(分值是三个集合分值的之和),根据分值默认排序展示即可。当然这里还有个步骤是根据page_id从hash中获取页面信息(比如页面链接),这里可以通过pipeline批量获取,最后把页面信息列表返回给前端浏览器按顺序展示即可。
总结
创建搜索引擎的关键就是创建“倒排索引”和“分词”,本次示例展示中没有进行分词,如果需要进行分词借助分词工具实现即可。另外使用redis的zset进行复合排序也很简单,关键就是要定义好多个分值的权重比,直接求交集或并集 即可完成排序。
另外本次示例中没有使用同义词(求并集即可),其实都可以根据自己的需要添加进去。理论上通过redis可以实现一个完善的搜索引擎,在没有ES的情况下使用redis做一个简单的“搜索引擎”也是件很容易的事。
相关推荐
分布式爬虫搜索引擎是一种高效的数据采集工具,它利用多个计算节点并行处理网页抓取任务,大大提升了爬虫的抓取速度和数据处理能力。在这个项目中,Scrapy和Redis两个强大的工具被结合在一起,构建了一个高效、可...
在本项目中,我们探索了一个基于Go语言实现的简单搜索引擎示例。这个示例利用了几个关键的技术...通过理解并分析这个项目,我们可以深入掌握Go语言、Redis、Colly和Gin-Gonic的使用,并了解到搜索引擎的基本工作原理。
综上所述,使用Java搭建搜索引擎涉及到网络爬虫、HTML解析、文本处理、索引构建、查询处理等多个环节。Java生态系统提供了丰富的库和工具,使得开发者能够高效地完成这一任务。结合压缩包中的章节内容,你可以逐步...
本文介绍了如何使用Scrapy框架结合Redis数据库构建分布式爬虫,并通过Django框架和ElasticSearch搭建了一个简易的搜索引擎。通过实践证明,该方法不仅提高了爬虫的效率,还能够更好地满足大规模数据的检索需求。对于...
本地Redis包可能包含Redis服务器的源代码、预编译二进制文件、配置文件以及相关的文档资料,方便用户在本地环境中搭建和使用Redis。 **1. Redis的数据类型** Redis支持多种数据类型,包括字符串(String)、哈希(Hash...
本系统以SpringBoot基础框架整合其他技术设计和搭建而成,选用webmagic框架实现单节点的网络爬虫系统,爬虫的生命周期为链接提取、页面下载、内容抽取、持久化...最后实现一个简单的web搜索页面,来模拟搜索引擎客户端
通过加载外部模块,你可以实现例如图形数据库、全文搜索引擎等附加功能,使Redis变得更加多功能化。 3. **性能优化**:Redis 5.0.5在性能方面也做了不少优化,比如对命令执行效率的提升,减少了内存碎片的产生,...
搜索引擎:Elasticsearch 6.4.3 安全:Spring Security 邮件任务:Spring Mail 分布式定时任务:Spring Quartz 日志:SLF4J(日志接口) + Logback(日志实现) 前端: Thymeleaf Bootstrap 4.x Jquery Ajax
而搜索引擎则是网站中不可或缺的一部分,它允许用户快速、准确地查找所需信息。"PHP搜索引擎.zip"可能是一个包含源代码和相关资源的压缩包,用于帮助开发者创建自定义的搜索引擎功能。下面将详细介绍PHP实现搜索引擎...
综上所述,Scrapy分布式爬虫搜索引擎将网络爬虫技术与分布式系统理念相结合,通过利用Redis实现爬虫的分布式化,运用Django搭建搜索引擎的后端框架,以及使用ElasticSearch存储和检索数据,大大提高了数据获取的效率...
随着大数据时代的到来,信息的获取与...然后选取ElasticSearch搭建搜索服务,同时提供了RESTful web接口;最后通过Django搭建可视化站点,供用户透明的对文章进行搜索。 关键词: 分布式爬虫; Scrapy; 搜索引擎; Redis
- spring-boot-starter-data-elasticsearch:对Elasticsearch搜索引擎的支持,用于分布式实时搜索和分析。 SpringCloud是由Netflix开源的一系列框架的集合,它提供了一种快速构建分布式系统的解决方案。SpringCloud...
2. **创建Node.js服务器**:使用Express或Koa等Node.js框架搭建服务器,设置路由来处理自动完成请求,通过`ioredis`等库与Redis通信,根据前端传来的部分输入查询匹配项。 3. **前端交互**:在HTML页面中,使用...
爬虫的应用领域非常广泛,目前利用爬虫技术市面上已经存在了比较成熟的搜索引擎产品,如百度、谷歌,以及其他垂直领域搜索引擎,这些都是非直接目的;还有一些推荐引擎,如今日头条,可以定向给用户推荐相关新闻;...
它以其简洁、高效和丰富的库支持,成为搭建各种功能网站的理想选择,其中包括搜索引擎的开发。"PHP实例开发源码—php搜查找搜索引擎.zip"就是这样一个实例,旨在帮助开发者学习和理解如何使用PHP来实现一个基本的...
在本项目实践中,我们将深入探讨如何使用Python分布式爬虫技术构建一个搜索引擎。这涉及到多个关键知识点,包括Python编程、网络爬虫原理、分布式系统以及数据处理与存储。 首先,Python编程是实现爬虫的基础,其...
本项目采用的技术栈包括MySQL数据库、Redis缓存、Spring Cloud Alibaba微服务框架、JWT(JSON Web Token)认证、Vue.js前端框架以及Element UI组件库,并结合MQ消息队列和ES搜索引擎,构建了一个智能商城系统——...
在本文中,我们将深入探讨如何利用Python技术来搭建一个分布式爬虫系统,并逐步构建一个简单的搜索引擎。 首先,我们需要理解分布式爬虫的基本概念。分布式爬虫是一种通过多台计算机协作抓取网页信息的系统,它可以...
还有对分区表、全文搜索和复制功能的增强,使得MySQL5.6更适合大规模、高并发的数据库应用场景。 【Yaf】 Yaf(Yet Another Framework)是由腾讯开发的一款PHP全栈框架,专为PHP7设计。Yaf利用PHP的C扩展实现,提供...
该项目是一个用于网页查询的轻量级搜索引擎。实现了从爬取网页,处理网页 服务器端基于Linux 平台、C/C++语言;客户端采用PHP 实现;爬虫采用Python 实现。 该项目是一个用于网页查询的轻量级搜索引擎。实现了从...