redis集合/有序集合在电商中应用-自动补全

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013862108/article/details/83862649

类似 淘宝 比如 搜索框中输入 :书 :下拉框中出现:

'书包女士',
'书包男款',
'书大',
'书包女赠送韩版',
'书皮纸韩国小清新',
'书斤',
'书包女双肩包学生简约',
'书双肩包',
'书包学生',
'书籍出版'

用户可以使用 上下箭头 或鼠标 选取

大致有两种思路:

一 使用一个有序集合 ;更节省内存; 使用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>';
    }

}

猜你喜欢

转载自blog.csdn.net/u013862108/article/details/83862649
今日推荐