這篇文章主要介紹“redis分詞索引法怎么用”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Redis分詞索引法怎么用”文章能幫助大家解決問題。
創(chuàng)新互聯(lián)建站于2013年開始,先為江門等服務(wù)建站,江門等地企業(yè),進行企業(yè)商務(wù)咨詢服務(wù)。為江門企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
這種方式是我實踐過后,結(jié)合上篇的前輩給的觀點覺得唯一比較可行且符合redis特性的方式,不過最終效率上還是比不過內(nèi)存。
詳細的實現(xiàn)思路清看Redis作者博客(參考資料1),這里的例子還是基于UserName,英文,并且只針對詞組做了長度為3的分詞,其他場景請自行擴展。
首先基于AutoComplete的字母搜索,那么我們需要對所有的Name做一個分詞,即:
abc => (a, ab, abc)
那么輸入a,我們就直接取set a里的內(nèi)容,輸入ab就直接取ab集合的內(nèi)容。那么我們開始轉(zhuǎn)換,首先我們需要對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條數(shù)據(jù),這里使用的是OrmLite的語法。
第二部:存入RedisSet,注意這里其實只是做了一個索引,并不保存具體的User內(nèi)容
接著搜索的時候我們可以實現(xiàn)如下:
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()) { //轉(zhuǎn)換成ids var ids = result.ToList().Select (i => i.ToString()); //按照keys獲取value ,事先已經(jīng)存好了Usersvar values = db.StringGet(ids.ToArray()); //構(gòu)造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()); } }
經(jīng)過實際的測試,這樣的寫法比前面的Keys確實好了不少,但是性能還是差強人意的。
這種方法是我在查閱了Redis的文檔之后,發(fā)現(xiàn)的,但是也就是試驗一下,估計也不能用做生產(chǎn)環(huán)境大規(guī)模查詢。
Scan根據(jù)數(shù)據(jù)結(jié)構(gòu)的不同分為了SCAN\HSCAN\SSCAN\ZSCAN,具體的信息請看文檔。我們這里采用了ZSCAN:
ZSCAN key cursor [MATCH pattern] [COUNT count]
這里cursor是搜索的迭代的一個游標,具體還沒弄明白,pattern就是匹配規(guī)則 count就是記錄條數(shù)
由于我使用的是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 >(); //構(gòu)造集合數(shù)據(jù)var list = users.Select(item =>{ var value = JsonConvert.SerializeObject(item); //構(gòu)造原始數(shù)據(jù)sourceData.Add(new KeyValuePair ("capqueen:users:" + item.Id, value)); //構(gòu)造數(shù)據(jù) return new SortedSetEntry(item.Name, item.Id); }); //添加進有序集合,采用name - id db.SortedSetAdd("capqueen:users:index", list.ToArray()); //添加港口數(shù)據(jù)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()) { //轉(zhuǎn)換成ids var ids = result.ToList().Select (i => i.ToString()); //按照keys獲取valuevar values = db.StringGet(ids.ToArray()); //構(gòu)造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; }
關(guān)于“Redis分詞索引法怎么用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。