摘要:自動補全也可以稱為自動提示,類似于在百度搜索的輸入框中輸入一個字符,下面會提示多個關鍵詞供參考。使用倒是一個很不錯的方案。雖然通過的通配符方式也可以實現自動提示,但是這種方法在中數據量較大時也存在性能問題。
自動補全也可以稱為自動提示,類似于在百度搜索的輸入框中輸入一個字符,下面會提示多個關鍵詞供參考。
假設:
輸入 a,會自動提示 apple、application、acfun、adobe;
輸入 ap,提示 apple、application;
輸入 ac,提示 acfun;
輸入 ad,提示 adobe。
看到這個功能需求,很簡單的方式就是在數據庫中直接使用 SQL LIKE 操作符來匹配,但是性能肯定是不行的。使用 Redis 倒是一個很不錯的方案。
Redis 是 KV 型數據庫,查詢都是基于 key 的,key 值必須具有唯一性。
雖然通過 key 的通配符方式也可以實現自動提示,但是這種方法在 Redis 中數據量較大時也存在性能問題。
回到上面的話題,本質就是我希望通過 a 獲取 apple、application、acfun、adobe,通過 ap 獲取 apple、application,以此類推。那么,需要查詢的值就應該作為 key,查詢結果應該作為 value。遵循這個思路,可以利用 Redis 的集合存儲這些值。為什么不用列表,而使用集合?因為我希望查詢出來的詞不會重復,而集合的特性就是元素唯一,性質決定用途,所以就使用集合。一般情況下,查詢出來的詞也會按照熱度頻率什么的排序,需要排序的話,就要使用 Redis 的有序集合。
以 word: 為前綴,方便管理和區別(保證唯一性),后面跟上要查詢的值,例如:word:a(其實這樣還是無法確保唯一性,就假設這個 key 在 Redis 中是唯一的)。
向集合中添加 關鍵詞:
bashZADD word:a 0 apple 0 application 0 acfun 0 adobe ZADD word:ap 0 apple 0 application ZADD word:app 0 apple 0 application ZADD word:appl 0 apple 0 application ZADD word:apple 0 apple ZADD word:appli 0 application ……
上面還沒有添加完成,完整添加的代碼如下:
phpredis = $redis; } public function add($word) { $len = mb_strlen($word, "UTF-8"); for ($i = 1; $i <= $len; $i++) { $sub = mb_substr($word, 0, $i, "UTF-8"); $this->redis->zAdd(self::PREFIX . $sub, 0, $word); } } }
看以上代碼,應該發現我給有序集合每個元素的 score 為 0,這個意義何在?不應該給每個詞不同的 score,以便給搜索結果排序嗎?確實如此,但是這樣會存在一個問題:某一個詞會出現在多個集合中,如果該詞的熱點要增加,那么就需要同時更新多個集合中該詞的 score。這顯然是不合理的。
那么到底應該怎么辦哩?再創建一個有序集合,專門用于存放這些詞和它們的 score。最后,將查詢結合和這個記錄熱度的集合做交集,就能得出按熱度排列后的結果。
設置這些詞的熱度:
bashZADD word_scores 100 apple 80 adobe 70 application 60 acfun
交集:
bashZINTERSTORE word_result 2 word_scores word:a WEIGHTS 1 1 ZRANGE word_result 0 -1 withscores
具體 PHP 實現代碼如下,僅供參考:
phpredis = $redis; } public function add($word) { $len = mb_strlen($word, "UTF-8"); for ($i = 1; $i <= $len; $i++) { $sub = mb_substr($word, 0, $i, "UTF-8"); $this->redis->zAdd(self::PREFIX . $sub, 0, $word); } } public function incScore($word, $score = 1) { return $this->redis->zIncrBy(self::WORDS_PREFIX, $score, $word); } public function search($keyword, $stop = 5) { $this->redis->zInter(self::RESULT_PREFIX, array(self::PREFIX . $keyword, self::WORDS_PREFIX), array(1, 1)); return $this->redis->zRevRange(self::RESULT_PREFIX, 0, $stop, true); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30241.html
摘要:嘮叨最近頻繁的給客戶做采集功能既然代碼無法公布所以一直想寫個思路類的文章既然是簡單的爬蟲那么一切自然以簡單為原則能少用的都少用比如和這兩個神兵利器就被我省略了打造這只蟲子就像是樵夫砍柴一般該磨刀還是要磨刀遠觀拜拜山頭對象站點國內知名電商平臺 嘮叨: 最近頻繁的給客戶做采集功能,既然代碼無法公布,所以一直想寫個思路類的文章.既然是簡單的爬蟲,那么一切自然以簡單為原則,能少用的都少用,比如...
摘要:完成狀態編寫中已完成維護中原文是一個使用編寫的開源支持網絡基于內存可選持久性的鍵值對存儲數據庫維基百科是目前業界使用廣泛的基于內存的數據庫。 完成狀態 [ ] 編寫中 [ ] 已完成 [x] 維護中 原文 Redis Redis是一個使用ANSI C編寫的開源、支持網絡、基于內存、可選持久性的鍵值對存儲數據庫 ------ 維基百科 Redis 是目前業界使用廣泛的基于內存的...
閱讀 1950·2021-10-12 10:12
閱讀 3077·2019-08-30 15:44
閱讀 846·2019-08-30 15:43
閱讀 2999·2019-08-30 14:02
閱讀 2082·2019-08-30 12:54
閱讀 3504·2019-08-26 17:05
閱讀 1986·2019-08-26 13:34
閱讀 1058·2019-08-26 11:54