zoukankan      html  css  js  c++  java
  • 搜索接口优化方案——幂集分词表

    前言:

        在业务开发中,有一些面向C端的搜索接口。比如根据商品名搜索,之前也提过通过ES解决,但这次主要以一种较为简单快捷的方式优化搜索速度。

     

    思路:

    1. 通过程序将所有商品名进行分词并幂集组合。
    2. 将所有商品名称幂集存入一张单独的表中。
    3. 每个分词对应一个商品ID。
    4. 搜索关键词对幂集表的分词模糊查询并取出商品ID。
    5. 对应的商品ID就是搜索出来的商品。

    编码:

    1. 数组元素的幂集函数。

    if (!function_exists('powerSet')) {
    
        function powerSet($array)
        {
    
            $results = array(array());
    
            foreach ($array as $element) {
    
                foreach ($results as $combination) {
    
                    $results[] = array_merge(array($element), $combination);
    
                }
    
            }
    
            return array_values($results);
        }
    }

    2. 搜索分词表创建。

    字段名类型描述
    id int 主键 ID
    goods_id int 商品编号
    search_path varchar 分词字符

    3. 生成搜索词数据命令, 以后可通过php think make:name 执行。

    <?php
    namespace appcommoncommand;
    
    use thinkconsoleCommand;
    use thinkconsoleInput;
    use thinkconsoleinputArgument;
    use thinkconsoleinputOption;
    use thinkconsoleOutput;
    
    use thinkDb;
    
    
    class MakeName extends Command{
    
        protected function configure(){
    
            $this->setName('make:name');
        }
    
        protected function execute(Input $input, Output $output){
    
    
            ini_set ('memory_limit', '512M');
    
            $output->info("===========BEGIN===========");
    
    
            $goods = Db::name("goods")->where("class_id",2)->cursor();
           
    
            foreach ($goods as  $goods_value) {
    
                $output->info("===========".$goods_value['goods_name']."===========");
    
                $goods_name = strtolower($goods_value['goods_name']);
    
                $name_array = explode(" ", $goods_name);
            
                $list = powerSet($name_array);
    
                $path = [];
    
                foreach ($list as  $value) {
    
                    if(!count($value)) continue;
    
                    $temp = array_reverse($value);
    
                    $data['goods_id'] = $goods_value['id'];
                    $data['search_path'] = implode("",$temp);
                    $path[] = $data;
                    $output->writeln($data['search_path']);
                    unset($data);
                }
    
    
                Db::name("search")->where("goods_id",$goods_value['id'])->delete();
    
                Db::name("search")->insertAll($path);
    
                unset($path);
            }
    
            $output->info("===========END===========");
        }
    }
    

     4. 搜索功能方法示例。

    /**
     * @Notes:
     * @param string $keyWord 搜索关键字
     * @param int $page 页码
     * @param int $size 每页数量
     * @return array
     */
    public function search($keyWord = '', $page = 1, $size = 10)
    {
    	$where = [];
    	$where[] = $keyWord . '%';
    	$where[] = str_replace(" ", "", $keyWord) . '%';
    	$keyArr = explode(" ", $keyWord);
    	foreach ($keyArr as $value) {
    		$where[] = trim($value) . '%';
    	}
    
    	$ids = Db::name("search")->where("search_path", "like", $where, "OR")->column("goods_id");
    
    	$ids = array_unique($ids);
    
    	$goods = 0;
    	$goods = Db::name("goods")->where("state", 1)->where("goods_name", "=", $keyWord)->value("id");
    	if ($goods && $page == 1) {
    
    		$key = array_search($goods, $ids);
    		unset($ids[$key]);
    	}
    
    	$map[] = ['state', '=', 1];
    	$map[] = ['delete_time', '=', 0];
    	$map[] = ['id', 'in', $ids];
    
    	$res = self::where($map)->field("id,goods_name")->order(['sort' => 'desc', 'id' => 'desc'])->page($page, $size)->select()->toArray();
    
    	if ($goods && $page == 1) {
    		if ($res) {
    			$first = $res[0];
    			$res[0] = ['id' => $goods, 'goods_name' => $keyWord];
    			$res[] = $first;
    		} else {
    			$res[0] = ['id' => $goods, 'goods_name' => $keyWord];
    		}
    
    	}
    	return $res;
    }

  • 相关阅读:
    Hibernate + mysql 查询伪劣时:= 出现 Space is not allowed after parameter prefix ':' MySQL异常
    Linux下使用Markdown
    第十六章:Java内存模型——Java并发编程实战
    第十五章:原子变量与非阻塞机制——Java并发编程实战
    第十四章:构建自定义的同步工具——Java并发编程实战
    第十三章:显示锁——Java并发编程实战
    访问者模式——HeadFirst设计模式学习笔记
    原型模式——HeadFirst设计模式学习笔记
    第十二章:并发程序的测试——Java并发编程实战
    备忘录模式——HeadFirst设计模式学习笔记
  • 原文地址:https://www.cnblogs.com/zerofc/p/13577850.html
Copyright © 2011-2022 走看看