Redis简单案例(一) 网站搜索的热搜词
对于一个网站来说,无论是商城网站还是门户网站,搜索框都是有一个比较重要的地位,它的存在可以说是
为了让用户更快、更方便的去找到自己想要的东西。对于经常逛这个网站的用户,当然也会想知道在这里比较“火”
的东西是什么,这个时候我们搜索框上的热词就起作用了。其实我觉得这一块的完善会对这个网站带来许多益处。
可能现在比较普遍的做法是把这些相应的信息存到我们的关系型数据库中,如sql server 和 oracle。方便起见
的话,可能每搜索一次就往表里插一次数据,用的时候要先统计数据,统计完后再排序,最后才展示。这种情况下,
如果搜索量很大的话,表的膨胀速度就会非常快,如果sql没写好,查询的时候估计会。。相比Redis,同等条件下,
Redis的速率肯定是会较优,毕竟是从内存中拿出来的。
案例用到的一些相关技术和说明:
技术 | 说明 |
.NET Core | 网站嘛,你懂的。有事没事用Core写写Demo,免得跟不上发展的脚步。 |
Redis | 存储搜索词,用了主从的模式,主写从读 |
Jquery-ui | 主要是用了里面的autocomplete |
开始正题之前,我们要确定用Redis中的那种数据结构,五种之中比较合适的应该是SortedSet,我们可以用成员来
作为搜索词,成员分数来作为搜索词的搜索次数,这样就可以很方便的来操作相关的数据了。
下面开始正题:
我们在开始的时候需要初始化一下数据。这里就直接在第一次运行的时候初始化。用上流水线的技术,速度还是
很可观的。初始化了70个搜索关键词(NBA球星),然后用随机数作为关键字的下标,去随机给这个关键字加1分。这
个分数就是这个关键字被搜索的次数。下面来看看初始化的相关代码:
public IActionResult Index()
{
//keys
IList<string> keys = new List<string>()
{
"kobe","johnson","jabbar","west","o'neal","baylor","mccann","worthy","gasol","chamberlain",
"fisher","odom","bynum","horry","rambis","riley","clarkson","Williams","young","Russell",
"ingram","randle","nance","brown","deng","yi","ariza","artest","walton","vujacic",
"james","paul","curry","park","yao","kevin","wade","rose","popovich","leonard",
"aldridge","ginobili","duncan","lavine","rubio","garnett","wiggins","westbrook","durant","ibaka",
"nowitzki","pierce","crawford","love","smith","iguodala","barnes","green","thompson","harden",
"lillard","mccollum","lin","jackson","nash","stoudemire","whiteside","dragic","Howard","batum"
}; //init
Random random = new Random();
var tran = _redis.GetTransaction();
for (int i = ; i < 1; i++)
{
tran.SortedSetIncrementAsync(_searchKey, keys[random.Next(, )], );
}
tran.ExecuteAsync(); return View();
}
这里是在加载这个页面的时候就把这些热搜词存进Redis中,这样我们才能有数据来演示啊。这里还用到了一个
非事务型的流水线。就是把要操作的指令存放到一个队列中,最后把这个队列扔到服务端去执行,这样就有效的减少
了不必要的网络传输,同时也提高了执行速度。
好了,初始数据有了,下面要做的就是用户在搜索的时候,根据用户的输入去匹配搜索次数多的关键字,展示最
Hot的10个,当然这个展示的个数是随我们定的,最后可以考虑把这个放到我们的配置文件中去,甚至是放到数据库中,
为的是灵活和方便维护。下面是我们在后台的处理逻辑:
public IActionResult GetHotKey(string key="")
{
if (string.IsNullOrEmpty(key))
{//default
var res = _redis.ZRevRange(_searchKey, , );
var list = (from i in res select i.ToString());
return Json(list);
}
else
{//by user input
var res = _redis.ZRevRange(_searchKey, , -);
var list = (from i in res select i.ToString()).Where(x => x.Contains(key)).Take().ToList();
return Json(list);
}
}
对于查询的处理是非常的简单的,用户不小心输入空格的时候就展示最热的10个关键词,如果用户有输入的话,就把
关键词中包含用户输入的展示出来。那么我们在页面上要做些什么呢?下面就是我们演示用的搜索框。
<div class="row">
<div class="col-md-6 col-md-offset-4" style="padding-top:50px;">
<input id="key" name="key" placeholder="search" class="form-control col-md-4">
<button class="btn btn-primary" type="button" id="searchSubmit">Search</button>
<div id="result"></div>
</div>
</div>
相应的js是写到 scripts 这个section中的,js的话是比较简单的就是用ajax去请求我们要展示的数据。更多的应该是
jquery-ui的api问题,大家也可以换用自己比较熟悉的组件,举一反三即可。下面是autocomplete的api ,如果有需要可
以去看一下。
@section scripts{
<script type="text/javascript">
$(function () {
//show hot keyword
$("#key").autocomplete({
source: function (request, response) {
$.ajax({
url: "@Url.Action("GetHotKey", "Auto")",
dataType: "json",
data: {
key: request.term
},
success: function (data) {
response(data);
}
});
},
});
</script>
}
那么用户点击了搜索之后我们要做些什么处理呢?无论是新的关键字还是已有的关键字,我们都是要做处理的,当然redis
中zincrby命令来处理这个是十分合适的,存在的就把分数加1,不存在就创建一个分数为1的成员。下面是搜索时的后台逻辑处理:
[HttpPost]
public IActionResult SetHotKey(string key)
{
if (!string.IsNullOrWhiteSpace(key))
{
_redis.ZIncrby(_searchKey,key);
//other
//...
return Json(new { code = "", msg = "OK" });
}
else
{
return Json(new { code = "", msg = "keyword can not be empty!" });
}
}
限制了用户不能搜索空关键字,在把这个关键字存储或者分数加一之后,就是展示我们的搜索的结果。这个搜索的结果一般
是从solr等全文检索的地方查出来的,不是我们讲的重点,所以就忽略了。然后我们还要加一段js去处理我们搜索的时候应该做的
操作。当然,都是些比较简单的操作。
//search
$("#searchSubmit").click(function () {
$.ajax({
url: "@Url.Action("SetHotKey", "Auto")",
dataType: "json",
type: "POST",
data: { key: $("#key").val() },
success: function (data) {
if (data.code == "000") {
$("<p>search successful!</p>").appendTo("#result");
} else {
$("<p>"+data.msg+"</p>").appendTo("#result");
}
}
});
});
在演示的时候,我们搜索了“我爱你”和“我不信”,在Redis的客户端我们找出搜索次数最少的6个,然后就可以看到我们那两
个关键字最的分数都是1。确定是刚插入的数据。
到这里,我们做的这个热搜词可以说是大功告成了。当然这可以说是最最最简单的一个雏形。我们还可以适当的添加一些
东西让这个功能变得更加完善。比如我可以在搜索展示的时候显示一下搜索的次数等。
最后是完整的控制器和页面代码:
using AutoCompleteDemo.Common;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq; namespace AutoCompleteDemo.Controllers
{
public class AutoController : Controller
{
private readonly IRedis _redis;
private readonly string _searchKey = "search";
public AutoController(IRedis redis)
{
_redis = redis;
} public IActionResult Index()
{
//keys
IList<string> keys = new List<string>()
{
"kobe","johnson","jabbar","west","o'neal","baylor","mccann","worthy","gasol","chamberlain",
"fisher","odom","bynum","horry","rambis","riley","clarkson","Williams","young","Russell",
"ingram","randle","nance","brown","deng","yi","ariza","artest","walton","vujacic",
"james","paul","curry","park","yao","kevin","wade","rose","popovich","leonard",
"aldridge","ginobili","duncan","lavine","rubio","garnett","wiggins","westbrook","durant","ibaka",
"nowitzki","pierce","crawford","love","smith","iguodala","barnes","green","thompson","harden",
"lillard","mccollum","lin","jackson","nash","stoudemire","whiteside","dragic","Howard","batum"
}; //init
Random random = new Random();
var tran = _redis.GetTransaction();
for (int i = ; i < ; i++)
{
tran.SortedSetIncrementAsync(_searchKey, keys[random.Next(, )], );
}
tran.ExecuteAsync(); return View();
} public IActionResult GetHotKey(string key="")
{
if (string.IsNullOrEmpty(key))
{//default
var res = _redis.ZRevRange(_searchKey, , );
var list = (from i in res select i.ToString());
return Json(list);
}
else
{//by user input
var res = _redis.ZRevRange(_searchKey, , -);
var list = (from i in res select i.ToString()).Where(x => x.Contains(key)).Take().ToList();
return Json(list);
}
} [HttpPost]
public IActionResult SetHotKey(string key)
{
if (!string.IsNullOrWhiteSpace(key))
{
_redis.ZIncrby(_searchKey,key);
//other
//...
return Json(new { code = "", msg = "OK" });
}
else
{
return Json(new { code = "", msg = "keyword can not be empty!" });
}
}
}
}
AutoController
@{
ViewData["Title"] = "Auto Complete";
}
<div class="row">
<div class="col-md-6 col-md-offset-4" style="padding-top:50px;">
<input id="key" name="key" placeholder="search" class="form-control col-md-4">
<button class="btn btn-primary" type="button" id="searchSubmit">Search</button>
<div id="result"></div>
</div>
</div>
@section scripts{
<script type="text/javascript">
$(function () {
//show hot keyword
$("#key").autocomplete({
source: function (request, response) {
$.ajax({
url: "@Url.Action("GetHotKey", "Auto")",
dataType: "json",
data: {
key: request.term
},
success: function (data) {
response(data);
}
});
},
}); //search
$("#searchSubmit").click(function () {
$.ajax({
url: "@Url.Action("SetHotKey", "Auto")",
dataType: "json",
type: "POST",
data: { key: $("#key").val() },
success: function (data) {
if (data.code == "000") {
$("<p>search successful!</p>").appendTo("#result");
} else {
$("<p>"+data.msg+"</p>").appendTo("#result");
}
}
});
});
});
</script>
}
Index.cshtml
Redis简单案例(一) 网站搜索的热搜词的更多相关文章
- Redis简单案例(二) 网站最近的访问用户
我们有时会在网站中看到最后的访问用户.最近的活跃用户等等诸如此类的一些信息.本文就以最后的访问用户为例, 用Redis来实现这个小功能.在这之前,我们可以先简单了解一下在oracle.sqlserve ...
- SpringDataRedis操作Redis简单案例
Jedis Jedis是Redis官方推出的一款面向Java的客户端,提供了很多接口供Java语言调用.可以在Redis官网下载,当然还有一些开源爱好者提供的客户端,如Jredis.SRP等等,推荐使 ...
- SpringBoot基础学习(一) SpringBoot概念、简单案例实现、单元测试及热部署讲解
SpringBoot概念 Spring优缺点分析 Spring优点 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品,无需开发重量级的 ...
- SparkStreaming实时日志分析--实时热搜词
Overview 整个项目的整体架构如下: 关于SparkStreaming的部分: Flume传数据到SparkStreaming:为了简单使用的是push-based的方式.这种方式可能会丢失数据 ...
- 纯前端实现词云展示+附微博热搜词云Demo代码
前言 最近工作中做了几个数据可视化大屏项目,其中也有用到了词云展示,以前做词云都是用python库来生成图片显示的,这次用了纯前端的实现(Ctrl+V真好用),同时顺手做个微博热搜的词云然后记录一下~ ...
- Redis简单案例(四) Session的管理
负载均衡,这应该是一个永恒的话题,也是一个十分重要的话题.毕竟当网站成长到一定程度,访问量自然也是会跟着增长,这个时候, 一般都会对其进行负载均衡等相应的调整.现如今最常见的应该就是使用Nginx来进 ...
- Redis简单案例(三) 连续登陆活动的简单实现
连续登陆活动,或许大家都不会陌生,简单理解就是用户连续登陆了多少天之后,系统就会送一些礼品给相应的用户.最常见的 莫过于游戏和商城这些.游戏就送游戏币之类的东西,商城就送一些礼券.正值国庆,应该也有不 ...
- Redis 实战 —— 11. 实现简单的社交网站
简介 前面介绍了广告定向的实现,它是一个查询密集型 (query-intensive) 程序,所以每个发给它的请求都会引起大量计算.本文将实现一个简单的社交网站,则会尽可能地减少用户在查看页面时系统所 ...
- Spring Data Solr操作solr的简单案例
Spring Data Solr简介 虽然支持任何编程语言的能力具有很大的市场价值,你可能感兴趣的问题是:我如何将Solr的应用集成到Spring中?可以,Spring Data Solr就是为了方便 ...
随机推荐
- HTML文档声明
前面的话 HTML文档通常以类型声明开始,该声明将帮助浏览器确定其尝试解析和显示的HTML文档类型.本文将详细介绍文档声明DOCTYPE 特点 文档声明必须是HTML文档的第一行.且顶格显示, ...
- ASP.NET WebApi OWIN 实现 OAuth 2.0
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. OAuth 允许用户提供一个令牌, ...
- GOF23设计模式之单例模式
·核心作用: -保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. ·常见应用场景: -Windows的Task Manager(任务管理器)就是很典型的单例模式 -Windows的Recy ...
- docker – 你应该知道的10件事
容器并不是一个全新的技术,但这并不妨碍Docker如风暴一样席卷整个世界. 如果你在IT圈里,你一定听说过Docker.就算与其他热门技术,如:Puppet/Chef,Hadoop或者MongoD ...
- AngularJS 系列 学习笔记 目录篇
目录: AngularJS 系列 01 - HelloWorld和数据绑定 AngularJS 系列 02 - 模块 (持续更新)
- Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录
一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...
- 一步步开发自己的博客 .NET版(1、基本显示)
前言 我们每个猿都有一个搭建自己独立博客的梦,我也不例外.以前想 现在想 以后也想.之所以一直迟迟没有着手,是因为难以跨出第一步.每次心里想着,等我以后技术好了再说,然后就没有然后了.以前用过word ...
- 从零开始,DIY一个jQuery(3)
在前两章,为了方便调试,我们写了一个非常简单的 jQuery.fn.init 方法: jQuery.fn.init = function (selector, context, root) { if ...
- 【腾讯Bugly经验分享】程序员的成长离不开哪些软技能?
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ce8068d4d44a246f72baf2 Dev Club 是一个交流移动 ...
- Maven入门详解
什么是Maven Maven,鼎鼎大名,在今天之前,我对于它一直是处于一种"只闻其名不见其人"的状态.之所以说"只闻其名",是因为Maven太有名了,它是Apa ...