Forráskód Böngészése

修改搜索引擎

stanley-king 8 éve
szülő
commit
2ead0b785d

+ 0 - 5
admin/control/mb_special.php

@@ -439,11 +439,6 @@ class mb_specialControl extends SystemControl
      */
     public function goods_listOp()
     {
-        //$model_goods = Model('goods');
-//        $condition = array();
-//        $condition['goods_name'] = array('like', '%' . $_REQUEST['keyword'] . '%');
-//        $goods_list = $model_goods->getGoodsOnlineList($condition, 'goods_id,goods_name,goods_promotion_price,goods_image,goods_storage', 10);
-
         $p['keyword'] = urlencode($_REQUEST['keyword']);
         $param = new search_param($p);
         $params = $param->format();

+ 193 - 3
helper/search/searcher.php

@@ -11,6 +11,7 @@ namespace search;
 use algorithm;
 use brand_helper;
 use category_helper;
+use Log;
 
 function mb_str_split( $string ) {
     return preg_split('/(?<!^)(?!$)/u', $string );
@@ -209,9 +210,88 @@ class goods_dict extends words
     }
 }
 
+class goods_info
+{
+    private $mGoods;
+    public function __construct()
+    {
+        $this->mGoods = [];
+    }
+
+    public function add($commonid, $price, $click, $salenum)
+    {
+        $commonid = intval($commonid);
+        if(!array_key_exists($commonid,$this->mGoods)) {
+            $this->mGoods[$commonid]['price'] = intval($price * 100 + 0.5);
+            $this->mGoods[$commonid]['click'] = intval($click);
+            $this->mGoods[$commonid]['salenum'] = intval($salenum);
+        }
+    }
+    public function goods($commonid)
+    {
+        return $this->mGoods[$commonid];
+    }
+
+    static public function click_asc($left,$right)
+    {
+        $t_l = intval($left['click']);
+        $t_r = intval($right['click']);
+
+        if($t_l > $t_r) return 1;
+        elseif($t_l < $t_r) return -1;
+        else return 0;
+    }
+    static public function click_desc($left,$right)
+    {
+        $t_l = intval($left['click']);
+        $t_r = intval($right['click']);
+
+        if($t_l > $t_r) return -1;
+        elseif($t_l < $t_r) return 1;
+        else return 0;
+    }
+
+    static public function salenum_asc($left,$right)
+    {
+        $t_l = intval($left['salenum']);
+        $t_r = intval($right['salenum']);
+
+        if($t_l > $t_r) return 1;
+        elseif($t_l < $t_r) return -1;
+        else return 0;
+    }
+    static public function salenum_desc($left,$right)
+    {
+        $t_l = intval($left['salenum']);
+        $t_r = intval($right['salenum']);
+
+        if($t_l > $t_r) return -1;
+        elseif($t_l < $t_r) return 1;
+        else return 0;
+    }
+    static public function price_asc($left,$right)
+    {
+        $t_l = intval($left['price']);
+        $t_r = intval($right['price']);
+
+        if($t_l > $t_r) return 1;
+        elseif($t_l < $t_r) return -1;
+        else return 0;
+    }
+    static public function price_desc($left,$right)
+    {
+        $t_l = intval($left['price']);
+        $t_r = intval($right['price']);
+
+        if($t_l > $t_r) return -1;
+        elseif($t_l < $t_r) return 1;
+        else return 0;
+    }
+}
+
 class searcher
 {
-    const filter = "goods_commonid,gc_id,brand_id,goods_mobile_name,goods_jingle,goods_spec";
+    const filter = "goods_commonid,gc_id,brand_id,goods_mobile_name,goods_jingle,goods_spec,goods_click,goods_salenum,goods_price";
 
     private $name_dict;
     private $jingle_dict;
@@ -221,6 +301,9 @@ class searcher
     private $category_dict;
     private $goods_dict;
 
+    private $goods_info;
+    private $price_cids;
+
     private static $stInstance;
 
     public static function instance()
@@ -255,6 +338,8 @@ class searcher
         $this->jingle_dict = new words();
         $this->spec_dict = new words();
         $this->goods_dict = new goods_dict();
+        $this->goods_info = new goods_info();
+        $this->price_cids = new valtokey();
 
         $mod_goods = Model('goods');
         $items = $mod_goods->getGoodsOnlineList(array(), self::filter, '', '', false);
@@ -280,7 +365,11 @@ class searcher
             $this->brand_dict->add_brand($brand_id,$common_id,$hot_id);
             $this->goods_dict->add_goods($common_id,$brand_id,$hot_id);
             $this->category_dict->add_hot($hot_id,$brand_id,$common_id);
+
+            $this->goods_info->add($common_id,$item['goods_price'],$item['goods_click'],$item['goods_salenum']);
+            $this->price_cids->add($common_id,intval($item['goods_price'] * 100 + 0.5));
         }
+        $this->price_cids->finish();
     }
 
     private function get_name($dict, $words)
@@ -486,10 +575,111 @@ class searcher
         }
 
         if(isset($keyword) && !empty($keyword)) {
-            return $this->keyword_serarch($keyword,$hot,$brand);
+            $result = $this->keyword_serarch($keyword,$hot,$brand);
         } else {
-            return $this->hb_search($hot,$brand);
+            $result = $this->hb_search($hot,$brand);
+        }
+
+        if(!empty($result))
+        {
+            $order = $params['order'];
+            $sort  = $params['sort'];
+
+            $page_count = 1;
+            if(!isset($params['page_no'])) {
+                $page_no = null;
+            } else {
+                $page_no = $params['page_no'];
+            }
+
+            if(!isset($params['page_size'])) {
+                $page_size = null;
+            } else {
+                $page_size = intval($params['page_size']);
+                $page_size = $page_size <= 0 ? 10 : $page_size;
+                $page_count = intval(count($result['cids']) / $page_size) + ((count($result['cids']) % $page_size) == 0 ? 0 : 1);
+            }
+
+            $cids = $this->sort_goods($result['cids'],$order,$sort,$page_no,$page_size);
+            $result['cids'] = $cids;
+            $result['page_count'] = $page_count;
         }
+
+        return $result;
+    }
+
+    private function sort_goods($cids,$order,$sort,$page_no,$page_size)
+    {
+        $goods = [];
+        foreach ($cids as $cid) {
+            $val = $this->goods_info->goods($cid);
+            $val['cid'] = $cid;
+            $goods[] = $val;
+        }
+
+        if($sort == 'asc')
+        {
+            if($order == 'cilck') {
+                uasort($goods,['\search\goods_info','click_asc']);
+            }
+            elseif($order == 'salenum') {
+                uasort($goods,['\search\goods_info','salenum_asc']);
+            }
+            elseif($order == 'price') {
+                uasort($goods,['\search\goods_info','price_asc']);
+            }
+            else {
+                Log::record("searcher sort_goods not order param");
+            }
+        }
+        else
+        {
+            if($order == 'cilck') {
+                uasort($goods,['\search\goods_info','click_desc']);
+            }
+            elseif($order == 'salenum') {
+                uasort($goods,['\search\goods_info','salenum_desc']);
+            }
+            elseif($order == 'price') {
+                uasort($goods,['\search\goods_info','price_desc']);
+            }
+            else {
+                Log::record("searcher sort_goods not order param");
+            }
+        }
+
+        $tmp = [];
+        foreach ($goods as $val) {
+            $tmp[] = $val;
+        }
+        $goods = $tmp;
+
+        $count = count($goods);
+        $result = [];
+        if($page_no == null || $page_size == null)
+        {
+            foreach ($goods as $val) {
+                $result[] = $val['cid'];
+            }
+        }
+        else
+        {
+            $page_no = $page_no <= 0 ? 1 : $page_no;
+            for ($start = ($page_no -1) * $page_size; $page_size > 0 && $start < $count; $page_size--,$start++) {
+                $result[] = $goods[$start]['cid'];
+            }
+        }
+
+        return $result;
+    }
+
+    public function match_price($params)
+    {
+        $price = $params['price'];
+        $page_no = $params['page_no'];
+        $page_size = $params['page_size'];
+
+        return $this->price_cids->findless(intval($price * 100 + 0.5),$page_no,$page_size);
     }
 
     private function get_ids($dict, $words)

+ 52 - 0
helper/search/util.php

@@ -225,3 +225,55 @@ class array_tree
         return $this->mTree[$hot]['subids'];
     }
 }
+
+class valtokey
+{
+    private $mKeys;
+    private $mValMap;
+    private $mKeyMap;
+    private $mCount;
+
+    public function __construct()
+    {
+        $this->mKeys   = [];
+        $this->mValMap = [];
+        $this->mKeyMap = [];
+        $this->mCount = 0;
+    }
+
+    public function add($key,$val)
+    {
+        if(algorithm::binary_search($this->mKeyMap,$key) == true) {
+            return false;
+        } else {
+            $pos = algorithm::lower_bonud($this->mKeyMap,$key);
+            algorithm::array_insert($this->mKeyMap,$pos,$key);
+        }
+
+        $pos = algorithm::lower_bonud($this->mValMap,$val);
+        algorithm::array_insert($this->mValMap,$pos,$val);
+        algorithm::array_insert($this->mKeys,$pos,$key);
+
+        return true;
+    }
+    public function finish() {
+        $this->mKeyMap = [];
+        $this->mCount = count($this->mKeys);
+    }
+
+    public function findless($val,$start,$length)
+    {
+        $pos = algorithm::upper_bound($this->mValMap,$val);
+        $pos = $pos - $start;
+        if($pos < 0 || $pos >= $this->mCount) {
+            return false;
+        }
+
+        $result = [];
+        for ($i = $pos; $i >= 0 && $length > 0; $i--,$length--) {
+            $result[] = $this->mKeys[$i];
+        }
+
+        return array('total' => $pos + 1,'cids' => $result);
+    }
+}

+ 32 - 1
helper/search_param.php

@@ -12,6 +12,8 @@ class search_param
     private $mKeyWord;
     private $mBrandId;
     private $mHotId;
+    private $mOrder;
+    private $mSort;
 
     public function __construct($param)
     {
@@ -33,9 +35,34 @@ class search_param
         if (!empty(trim($param['hot_id']))) {
             $this->mHotId = intval($param['hot_id']);
         }
+
+        if (!empty(trim($param['sort']))) {
+            $this->mOrder = strtolower(trim($param['sort']));
+        } else {
+            $this->mOrder = 'click';
+        }
+
+        //下面两个参数和客户端定义反了
+        $this->mOrder = 'click';
+        if (!empty($param['sort']))
+        {
+            $order = strtolower(trim($param['sort']));
+            if(in_array($order,array('click','salenum','price'))) {
+                $this->mOrder = $order;
+            }
+        }
+
+        $this->mSort = 'desc';
+        if (!empty($param['order']))
+        {
+            $sort = strtolower(trim($param['order']));
+            if(in_array($sort,array('asc','desc'))) {
+                $this->mSort = $sort;
+            }
+        }
     }
 
-    public function format()
+    public function format($page_no = null,$page_size = null)
     {
         if (empty($this->mKeyWord) && $this->mBrandId == 0 && $this->mHotId == 0) {
             return false;
@@ -44,6 +71,10 @@ class search_param
             $result['keyword'] = $this->mKeyWord;
             $result['brand_id'] = $this->mBrandId;
             $result['hot_id'] = $this->mHotId;
+            $result['order'] = $this->mOrder;
+            $result['sort'] = $this->mSort;
+            $result['page_no'] = $page_no;
+            $result['page_size'] = $page_size;
 
             return $result;
         }

+ 18 - 33
mobile/control/search.php

@@ -28,7 +28,7 @@ class searchControl extends mobileHomeControl
     public function indexOp()
     {
         $param = new search_param($_GET);
-        $params = $param->format();
+        $params = $param->format($this->page_no(),$this->page_size());
 
         if($params == false) {
             return self::outsuccess(array('special_list' => null,
@@ -52,15 +52,11 @@ class searchControl extends mobileHomeControl
         }
 
         $cids = $result['cids'];
-        $order = $this->order($_GET['sort'], $_GET['order']);
-
         $model_goods = Model('goods');
-        $goods_list = $model_goods->getGoodsListByColorDistinct(array('goods_commonid' => array('in',$cids)),
-            goods_helper::fieldstr, $order, $this->page_size());
-        $page_count = $model_goods->gettotalpage();
-        $model_goods->cls();
+        $items = $model_goods->getGoodsListByColorDistinct(array('goods_commonid' => array('in',$cids)),goods_helper::fieldstr,'','');
+        $page_count = $result['page_count'];
 
-        if(empty($goods_list))
+        if(empty($items))
         {
             return self::outsuccess(array('special_list' => null,
                 'summary'  => null,
@@ -71,6 +67,20 @@ class searchControl extends mobileHomeControl
         }
         else
         {
+            $tmp =[];
+            foreach ($items as $item) {
+                $commonid = intval($item['goods_commonid']);
+                $tmp[$commonid] = $item;
+            }
+
+            $goods_list = [];
+            foreach ($cids as $cid)
+            {
+                if(array_key_exists($cid,$tmp)) {
+                    $goods_list[] = $tmp[$cid];
+                }
+            }
+
             $blocks = [];
             if($this->page_no() == 1)
             {
@@ -127,31 +137,6 @@ class searchControl extends mobileHomeControl
         }
     }
 
-    private function order($field, $order)
-    {
-        if(empty($field)) {
-            return 'is_own_shop desc,goods_click desc';
-        }
-        else
-        {
-            if(empty($order)) {
-                $order = 'desc';
-            } elseif($order == 'desc') {
-                $order = 'desc';
-            } else {
-                $order = 'asc';
-            }
-
-            if ($field == 'salenum') {
-                return 'goods_salenum desc';
-            } elseif($field == 'price') {
-                return 'goods_price ' . $order;
-            } else {
-                return 'goods_click desc';
-            }
-        }
-    }
-
     public function suggest_wordsOp()
     {
         $keyword = $_GET['keyword'];

+ 14 - 8
test/TestSearch.php

@@ -48,17 +48,23 @@ class TestSearch extends PHPUnit_Framework_TestCase
     public function testSearcher()
     {
         $searcher = new search\searcher();
-        $result = $searcher->get_result(array('keyword' => '相宜本草'));
-    }
+        $searcher->init();
+        $result = $searcher->get_result(array('keyword' => '妮维雅','order' =>'price','sort' => 'desc','page_no' => 1,'page_size' => 10));
 
-    public function testRequest()
-    {
-        for($i = 0; $i < 1000; ++$i) {
-            $result = search\tcp_client::instance()->get_result(array('keyword' => '相宜本草'));
-            //Log::record("testRequest {$i}",Log::DEBUG);
-        }
+
+        $result = $searcher->match_price(array('price' => 50,'page_no' => 1,'page_size' => 10));
+        $x = 100;
     }
 
+
+//    public function testRequest()
+//    {
+//        for($i = 0; $i < 1000; ++$i) {
+//            $result = search\tcp_client::instance()->get_result(array('keyword' => '相宜本草'));
+//            //Log::record("testRequest {$i}",Log::DEBUG);
+//        }
+//    }
+
     public function testBrandSpecia()
     {
         $brands = new brands_special();