1. 程式人生 > >redis集合/有序集合在電商中應用-自動補全

redis集合/有序集合在電商中應用-自動補全

類似 淘寶 比如 搜尋框中輸入 :書 :下拉框中出現:

'書包女士',
'書包男款',
'書大',
'書包女贈送韓版',
'書皮紙韓國小清新',
'書斤',
'書包女雙肩包學生簡約',
'書雙肩包',
'書包學生',
'書籍出版'

使用者可以使用 上下箭頭 或滑鼠 選取

大致有兩種思路:

一 使用一個有序集合 ;更節省記憶體; 使用redis 對集合成員的預設排序(當元素的分數一樣時會按照元素值的字典順序排序);

二:使用多個集合(有序,無序都可以);可能更浪費記憶體,因為 像“書包女雙肩包學生簡約” 就在9個集合中都有;但是可以給標籤加score(權重);兩種方法各有優缺點:

程式碼如下:

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Tag extends CI_Controller {

	public function index()
	{
	   
           $this->load->library('predis');
           $this->load->view('welcome_message');
	}



	public function tag_data(){

	    //標籤資料
	    //資料從淘寶找的
        //生產中資料可以從MySQL中獲取
	    $tag_data = array(
            '書包女士',
            '書包男款',
            '書大',
            '書包女贈送韓版',
            '書皮紙韓國小清新',
            '書斤',
            '書包女雙肩包學生簡約',
            '書雙肩包',
            '書包學生',
            '書籍出版'
        );

	    return $tag_data;
    }
    /**
     * @param $word   要拆分的標籤
     * 如 :$word == '書包女士'
     * 將拆分為 : 書   書包  書包  書包女   書包女士*
     * * 作用標記完整標籤,當前也可以使用如# $這樣的標籤;
     */
	public function get_prefixes($word){
	    $arr = array();
        echo $length = mb_strlen($word,'utf8');
        for($i = 1; $i<= $length; $i++){

            $item = mb_substr($word,0,$i);
            if($i == $length){
                array_push($arr,$item.'*');
            }else{
                array_push($arr,$item);
            }

        }
        return $arr;
    }

    public function ready_autocomplete(){

	    $tag_arr = $this->tag_data();
	    foreach ($tag_arr as $val){
	        $item = $this->get_prefixes($val);
	        foreach ($item as $word){
	            //array_push($argv,array(0,$word));
                $this->predis->zadd('autocomplete',0,$word);
            }
        }


    }

    public function view_autocomplete(){
	    $autocomplete = $this->predis->zrange('autocomplete',0,-1);
	    echo 'autocomplete';
	    echo '<pre>';
	    var_dump($autocomplete);
	    echo '</pre>';
    }

    public function is_exists_mbstrlen(){
	    echo  function_exists('mb_strlen');
    }


    public function test(){
	    $input = $this->input->get('input',true);

	    //zrank 返回有序集合key 中成員member的排名; 排名從0開始
        $zrank = $this->predis->zrank('autocomplete',$input); //
        echo 'zrank:';
        var_dump($zrank);
	    if(isset($zrank)){
	        $values = $this->predis->zrange('autocomplete',$zrank,$zrank+100);
	        echo 'values:';
	        var_dump($values);

	        foreach ($values as $val){
	            if(mb_substr($val,mb_strlen($val)-1) == '*' && $input == mb_substr($val,0,mb_strlen($input))){
	                echo mb_substr($val,0,mb_strlen($val)-1)."<br/>";
                }
            }
        }
    }

    /**
     * 第二種方法, 標籤,
     * 如 書包男款  被拆集合鍵(有序,無序都可以)為: 書 書包  書包男;  每一個都是集合
     * 有序集合鍵可以 利用 sort 配合by 把最熱門的標籤排在前面
     *
     * 兩種方法對比 :第一種使用一個集合 更節省記憶體; 第二種;使用多個集合 可以給完整標籤設定分數,給標籤加權重。各有優缺點
     */
    public function ready2(){
	    $tag_arr = $this->tag_data();

	    if(!empty($tag_arr) && is_array($tag_arr)){
	        foreach($tag_arr as $key=>$val){
	            $this->tagSet2($val);
            }
        }
    }

    /**
     * @param $tag
     * 將標籤存入集合
     */
    public function tagSet2($tag){
        echo $length = mb_strlen($tag,'utf8');
        for($i = 1; $i< $length; $i++){

            $key = mb_substr($tag,0,$i);
            //$this->predis->sadd($key,$tag);

            $score = mt_rand(0,100);
            $this->predis->zadd($key,$score,$tag);

        }
    }

    public function test2(){
        $input = $this->input->get('input',true);
        //$members  = $this->predis->smembers($input);
        //$members = $this->predis->zrange($input,0,-1,'withscores');

        //帶排序
        $members = $this->predis->zrevrangebyscore($input,'+inf',0,'withscores','limit',0,3);
        echo '<pre>';
        var_dump($members);
        echo '</pre>';
    }

}