Explorar o código

搜索功能替换为独立的搜索服务器 meilisearch

joe %!s(int64=3) %!d(string=hai) anos
pai
achega
feab319d5b

+ 13 - 0
README.tw.md

@@ -0,0 +1,13 @@
+# tw 对 CRMEB3.0 的增强与削弱
+
+tw 对 CRMEB3.0 的修改并非面向开源社区或第三方需求,而是完全基于 tw 自身的需求。
+
+## TODO
+
+- 独立的搜索引擎
+- event 异步处理
+- 增加/删除/合理化日志
+
+## Changed
+
+详情暂时看 git log

+ 3 - 1
app/admin/model/store/StoreProduct.php

@@ -129,7 +129,9 @@ class StoreProduct extends BaseModel
     public static function ProductList($where)
     {
         $model = self::getModelObject($where);
-        if ($where['excel'] == 0) $model = $model->page((int)$where['page'], (int)$where['limit']);
+        if ($where['excel'] == 0) {
+            $model = $model->page((int)$where['page'], (int)$where['limit']);
+        }
         $data = ($data = $model->select()) && count($data) ? $data->toArray() : [];
         foreach ($data as &$item) {
             $cateName = CategoryModel::where('id', 'IN', $item['cate_id'])->column('cate_name', 'id');

+ 72 - 3
tw/command/Maintain.php

@@ -6,7 +6,6 @@ use app\admin\model\store\StoreProduct;
 use app\admin\model\store\StoreProductAttr;
 use app\admin\model\store\StoreProductAttrResult;
 use app\admin\model\store\StoreProductAttrValue;
-use app\admin\model\system\SystemLog;
 use app\models\store\StoreProductRule;
 use think\console\Command;
 use think\console\Input;
@@ -30,7 +29,7 @@ class Maintain extends Command
     protected function configure()
     {
         $this->setName('maintain')
-            ->addArgument('category', Argument::REQUIRED, 'act|prod|trash|reindex|none')
+            ->addArgument('category', Argument::REQUIRED, 'act|prod|trash|reindex|test_reindex|none')
             ->setDescription('maintain some application data.');
     }
 
@@ -317,16 +316,86 @@ class Maintain extends Command
      * 2.用于关键字搜索
      * 3.用于按价格/销量/好评度/上线时间排序
      * 
+     * TODO:
      * - 新增/上架商品: 新增索引
      * - 删除/下架商品:删除索引
+     * - 編輯商品:重新索引
+     * 
+     * cur: 當前新增的商品不會立即出現在搜索結果,而是每次都重新索引全部。
+     * 因为这样实现简单,另外商品总的数据量不会很大
+     * 
      */
     protected function reindex()
     {
+        $ml = new Client(config('meilisearch.addr'), config('meilisearch.key'));
+        // remove first
+        $ml->deleteIndex('products');
+        // rebuild
+        $idx = $ml->index('products', 'id');
+        // setup
+
+        $idx->updateSearchableAttributes([
+            'store_name',
+            'store_info',
+            'keyword',
+        ]);
+        $idx->updateFilterableAttributes([
+            'cate_id',
+            'price',
+            'is_hot',
+            'is_benefit',
+            'is_best',
+            'is_new',
+            'add_time',
+            'is_good',
+        ]);
+        $idx->updateSortableAttributes([
+            'price',
+            'sales',
+            'cost',
+            'browse',
+        ]);
+        // get all products
+        $page = 1;
+        $limit = 20;
+        $count = 0;
+        while (true) {
+            $products = StoreProduct::where('is_del', 0)
+                ->where('stock', '>', 0)
+                // ->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')
+                ->page($page, $limit)->select()->toArray();
+                
+            $count += count($products);
+
+            if (count($products) > 0) {
+                $idx->addDocuments($products, 'id');
+            }
+            // no more rows
+            if (count($products) < $limit) {
+                break;
+            }
 
+            // loop
+            $page += 1;
+        }
+        echo "re-index all products finished. total=$count" . PHP_EOL;
     }
 
-    protected function none()
+    protected function _all_products_on_sale()
+    {
+    }
+
+    protected function test_reindex()
     {
 
     }
+    
+    protected function none()
+    {
+    }
 }

+ 49 - 0
tw/lib/search/Searcher.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace tw\lib\search;
+
+abstract class Searcher
+{
+    /**
+     * remove an index (container of documents)
+     */
+    function removeIndex(string $name)
+    {
+
+    }
+
+    /**
+     * switch current document indexing process to new index
+     */
+    function switchIndex(string $name)
+    {
+
+    }
+
+    /**
+     * index a document
+     */
+    function indexDoc(array $doc)
+    {
+    }
+
+    /**
+     * remove an indexed document
+     */
+    function removeDoc(string $docId)
+    {
+
+    }
+
+    /**
+     * rebuild all indexes of products
+     * 
+     * internally, this will first remove all indexed docs,
+     * and second, index products one by one(or batchly, it depends on the way the provider's API implements)
+     * 
+     */
+    function reindexProducts()
+    {
+
+    }
+}

+ 3 - 3
tw/lib/Meili.php → tw/lib/search/providers/Meili.php

@@ -1,6 +1,6 @@
 <?php
 
-namespace tw\lib;
+namespace tw\lib\search\proviers;
 
 /**
  * Meilisearch API for twong.
@@ -8,12 +8,12 @@ namespace tw\lib;
 class Meili
 {
 
-    public function indexProduct($product)
+    public function index($docs)
     {
 
     }
 
-    public function unIndexProduct($productId)
+    public function remove($docId)
     {
 
     }