Browse Source

实现手动索引,前端搜索

joe 3 years ago
parent
commit
85da3a6b42
2 changed files with 84 additions and 35 deletions
  1. 78 28
      app/models/store/StoreProduct.php
  2. 6 7
      tw/command/Maintain.php

+ 78 - 28
app/models/store/StoreProduct.php

@@ -16,6 +16,7 @@ use app\models\store\{
 };
 use app\models\user\UserSearch;
 use think\facade\Config;
+use MeiliSearch\Client;
 
 /**
  * TODO 产品Model
@@ -89,6 +90,38 @@ class StoreProduct extends BaseModel
         return self::where('is_del', 0)->where('is_show', 1)->where('mer_id', 0);
     }
 
+    /**
+     * 独立搜索
+     * 
+     * v1. 使用 meilisearch 作为后端
+     * 
+     * @param string $keywords 搜索关键字
+     * @return json 直接返回搜索结果到前端
+     */
+    protected static function search_by_keywords($keywords, $uid)
+    {
+        $show_benefit = Config::get('app.show_benefit', false);
+
+        $ml = new Client(config('meilisearch.addr', '127.0.0.1'), config('meilisearch.key'));
+        $idx = $ml->index('products');
+        $hits = $idx->search($keywords)->getHits();
+
+        $list = [];
+        $fields = 'id,store_name,cate_id,image,price,stock,spec_type';
+        $fields = explode(',', $fields);
+        // shrink hits in-place
+        foreach ($hits as $hit) {
+            $item = [];
+            foreach ($fields as $field) {
+                $item[$field] = $hit[$field];
+            }
+            $item['sales'] = $hit['sales'] + $hit['ficti'];
+
+            $list[] = $item;
+        }
+        return self::setLevelPrice($list, $uid);
+    }
+
     public static function getProductList($data, $uid)
     {
         $sId = $data['sid'];    // category id
@@ -113,40 +146,48 @@ class StoreProduct extends BaseModel
             });
         }
         if (!empty($keyword)) {
-            $model->where('keyword|store_name', 'LIKE', htmlspecialchars("%$keyword%"));
             UserSearch::InsertHistory($uid ?? 1, $keyword);
+
+            return self::search_by_keywords($keyword, $uid);
+            // $model->where('keyword|store_name', 'LIKE', htmlspecialchars("%$keyword%"));
+        }
+        if ($news != 0) {
+            $model->where('is_new', 1);
         }
-        if ($news != 0) $model->where('is_new', 1);
         $baseOrder = '';
         if ($priceOrder) $baseOrder = $priceOrder == 'desc' ? 'price DESC' : 'price ASC';
         // if($salesOrder) $baseOrder = $salesOrder == 'desc' ? 'sales DESC' : 'sales ASC';//真实销量
         if ($salesOrder) $baseOrder = $salesOrder == 'desc' ? 'sales DESC' : 'sales ASC'; //虚拟销量
-        if ($baseOrder) $baseOrder .= ', ';
+        if ($baseOrder) {
+            $baseOrder .= ', ';
+        }
         $model->order($baseOrder . 'sort DESC, add_time DESC');
         $show_benefit = Config::get('app.show_benefit', false);
         $fields = 'id,store_name,cate_id,image,IFNULL(sales,0) + IFNULL(ficti,0) as sales,price,stock,spec_type';
         if ($show_benefit) {
             $fields .= ',cost';
         }
-        $list = $model->page((int)$page, (int)$limit)->field($fields)->select()->each(function ($item)
-        use ($uid, $type, $show_benefit, $sId) {
-            if ($type) {
-                if ($item['spec_type']) {
-                    $item['is_att'] = StoreProductAttrValueModel::where(['product_id' => $item['id'], 'type' => 0])->count() ? true : false;
-                } else {
-                    $item['is_att'] = false;
+        $list = $model->page((int)$page, (int)$limit)
+            ->field($fields)
+            ->select()
+            ->each(function ($item) use ($uid, $type, $show_benefit, $sId) {
+                if ($type) {
+                    if ($item['spec_type']) {
+                        $item['is_att'] = StoreProductAttrValueModel::where(['product_id' => $item['id'], 'type' => 0])->count() ? true : false;
+                    } else {
+                        $item['is_att'] = false;
+                    }
+                    if ($uid) $item['cart_num'] = StoreCart::where('is_pay', 0)->where('is_del', 0)->where('is_new', 0)->where('type', 'product')->where('product_id', $item['id'])->where('uid', $uid)->value('cart_num');
+                    else $item['cart_num'] = 0;
+                    if (is_null($item['cart_num'])) $item['cart_num'] = 0;
                 }
-                if ($uid) $item['cart_num'] = StoreCart::where('is_pay', 0)->where('is_del', 0)->where('is_new', 0)->where('type', 'product')->where('product_id', $item['id'])->where('uid', $uid)->value('cart_num');
-                else $item['cart_num'] = 0;
-                if (is_null($item['cart_num'])) $item['cart_num'] = 0;
-            }
-            // show benefit
-            if ($show_benefit) {
-                $rate = getRate($sId);
-                $item['reputation'] = '赔付' . getReputation($item, $rate);
-                unset($item['cost']);
-            }
-        });
+                // show benefit
+                if ($show_benefit) {
+                    $rate = getRate($sId);
+                    $item['reputation'] = '赔付' . getReputation($item, $rate);
+                    unset($item['cost']);
+                }
+            });
         $list = count($list) ? $list->toArray() : [];
         if (!empty($list)) {
             foreach ($list as $k => $v) {
@@ -309,20 +350,25 @@ class StoreProduct extends BaseModel
             $discount = bcsub(1, bcdiv($discount, 100, 2), 2);
         }
         //如果不是数组直接执行减去会员优惠金额
-        if (!is_array($list))
+        if (!is_array($list)) {
             //不是会员原价返回
-            if ($levelId)
+            if ($levelId) {
                 //如果$isSingle==true 返回优惠后的总金额,否则返回优惠的金额
                 return $isSingle ? bcsub($list, bcmul($discount, $list, 2), 2) : bcmul($discount, $list, 2);
-            else
+            } else {
                 return $isSingle ? $list : 0;
+            }
+        }
+
         //当$list为数组时$isSingle==true为一维数组 ,否则为二维
-        if ($isSingle)
+        if ($isSingle) {
             $list['vip_price'] = isset($list['price']) ? bcsub($list['price'], bcmul($discount, $list['price'], 2), 2) : 0;
-        else
+        } else {
             foreach ($list as &$item) {
                 $item['vip_price'] = isset($item['price']) ? bcsub($item['price'], bcmul($discount, $item['price'], 2), 2) : 0;
             }
+        }
+
         return $list;
     }
 
@@ -358,9 +404,13 @@ class StoreProduct extends BaseModel
         foreach ($cateList as $cate) {
             $cid[] = $cate['id'];
         }
-        $model = self::where('cate_id', 'IN', $cid)->where('is_show', 1)->where('is_del', 0)
+        $model = self::where('cate_id', 'IN', $cid)
+            ->where('is_show', 1)
+            ->where('is_del', 0)
             ->field($field)->order('sort DESC,id DESC');
-        if ($limit) $model->limit($limit);
+        if ($limit) {
+            $model->limit($limit);
+        }
         return $model->select();
     }
 

+ 6 - 7
tw/command/Maintain.php

@@ -331,9 +331,9 @@ class Maintain extends Command
         // remove first
         $ml->deleteIndex('products');
         // rebuild
-        $idx = $ml->index('products', 'id');
-        // setup
+        $idx = $ml->index('products');
 
+        // setup
         $idx->updateSearchableAttributes([
             'store_name',
             'store_info',
@@ -362,14 +362,14 @@ class Maintain extends Command
         while (true) {
             $products = StoreProduct::where('is_del', 0)
                 ->where('stock', '>', 0)
-                // ->where('is_show', 1)
+                ->where('is_show', 1)
                 ->field('id,image,slider_image,store_name,
                     store_info,keyword,cate_id,price,vip_price,ot_price,postage,
                     unit_name,sort,sales,stock,
                     is_hot,is_benefit,is_best,is_new,add_time,is_postage, 
-                    give_integral,cost,is_good,ficti,browse')
+                    give_integral,cost,is_good,ficti,spec_type,browse')
                 ->page($page, $limit)->select()->toArray();
-                
+
             $count += count($products);
 
             if (count($products) > 0) {
@@ -392,9 +392,8 @@ class Maintain extends Command
 
     protected function test_reindex()
     {
-
     }
-    
+
     protected function none()
     {
     }