Redis分词索引法怎么用
这篇文章主要介绍"Redis分词索引法怎么用"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"Redis分词索引法怎么用"文章能帮助大家解决问题。
分词索引法
这种方式是我实践过后,结合上篇的前辈给的观点觉得唯一比较可行且符合redis特性的方式,不过最终效率上还是比不过内存。
详细的实现思路清看Redis作者博客(参考资料1),这里的例子还是基于UserName,英文,并且只针对词组做了长度为3的分词,其他场景请自行扩展。
首先基于AutoComplete的字母搜索,那么我们需要对所有的Name做一个分词,即:
abc => (a, ab, abc)
那么输入a,我们就直接取set a里的内容,输入ab就直接取ab集合的内容。那么我们开始转换,首先我们需要对User表的姓名进行分词:
var redis = ConnectionMultiplexer.Connect("localhost");var db = redis.GetDatabase();for (var i = 1; i < 4; i++){ var data = dbCon.Lookup(string.Format(@"select words, id from ( select Row_number() over (partition by words order by name) as rn,id,words from ( select id, SUBSTRING(name, 1, {0}) as words, name from User ) as t ) t2 where rn <= {1} and words != '' and words is not null", i, 20)); data.ForEach((key, item) => { db.SetAdd("capqueen:Cache:user:" + key.ToLower(), item.Select (j => j).ToArray()); });}
第一步:采用SQL,分组排序筛选出每个分词的前20条数据,这里使用的是OrmLite的语法。
第二部:存入RedisSet,注意这里其实只是做了一个索引,并不保存具体的User内容
接着搜索的时候我们可以实现如下:
public ListSearchWords(string keywords){ var redis = ConnectionMultiplexer.Connect("localhost"); var db = redis.GetDatabase(); var result = db.SetMembers("capqueen:Cache:user:" + keywords.ToLower()); var users = new List (); if (result.Any()) { //转换成ids var ids = result.ToList().Select (i => i.ToString()); //按照keys获取value ,事先已经存好了Usersvar values = db.StringGet(ids.ToArray()); //构造List Json以加速解析var portsJson = new StringBuilder("["); values.ToList().ForEach(item =>{ if (!string.IsNullOrWhiteSpace(item)) { portsJson.Append(item).Append(","); } }); portsJson.Append("]"); users = JsonConvert.DeserializeObject >(portsJson.ToString()); }}
经过实际的测试,这样的写法比前面的Keys确实好了不少,但是性能还是差强人意的。
Scan搜索法
这种方法是我在查阅了Redis的文档之后,发现的,但是也就是试验一下,估计也不能用做生产环境大规模查询。
Scan根据数据结构的不同分为了SCAN\HSCAN\SSCAN\ZSCAN,具体的信息请看文档。我们这里采用了ZSCAN:
ZSCAN key cursor [MATCH pattern] [COUNT count]
这里cursor是搜索的迭代的一个游标,具体还没弄明白,pattern就是匹配规则 count就是记录条数
由于我使用的是StackExchange.Redis,它提供的zscan方法是:
IEnumerable SortedSetScan(RedisKey key, RedisValue pattern = null, int pageSize = 10, long cursor = 0, int pageOffset = 0, CommandFlags flags = CommandFlags.None);
public void CreateTerminalCache(Listusers){ if (users == null) return; var db = ConnectionMultiplexer.GetDatabase(); var sourceData = new List >(); //构造集合数据var list = users.Select(item =>{ var value = JsonConvert.SerializeObject(item); //构造原始数据sourceData.Add(new KeyValuePair ("capqueen:users:" + item.Id, value)); //构造数据 return new SortedSetEntry(item.Name, item.Id); }); //添加进有序集合,采用name - id db.SortedSetAdd("capqueen:users:index", list.ToArray()); //添加港口数据key-value db.StringSet(sourceData.ToArray(), When.Always, CommandFlags.None);}
然后搜索的时候如下:
public ListGetUserByWord(string words){ var db = ConnectionMultiplexer.GetDatabase(); //搜索var result = db.SortedSetScan("capqueen:users:index", words + "*", 10, 1, 30, CommandFlags.None).Take(30).ToList(); var users = new List (); if (result.Any()) { //转换成ids var ids = result.ToList().Select (i => i.ToString()); //按照keys获取valuevar values = db.StringGet(ids.ToArray()); //构造List Json以加速解析var portsJson = new StringBuilder("["); values.ToList().ForEach(item =>{ if (!string.IsNullOrWhiteSpace(item)) { portsJson.Append(item).Append(","); } }); portsJson.Append("]"); users = JsonConvert.DeserializeObject >(portsJson.ToString()); } return users;}
关于"Redis分词索引法怎么用"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。