Переглянути джерело

Merge pull request #1745 from visuddhinanda/agile

改为每次查询连接数据库
visuddhinanda 2 роки тому
батько
коміт
0ad65419b4

+ 2 - 1
rpc/tulip/tulip/composer.json

@@ -2,7 +2,8 @@
   "require": {
     "grpc/grpc": "v1.57.0",
     "google/protobuf": "v3.23.2",
-    "guzzlehttp/guzzle": "^7.8"
+    "guzzlehttp/guzzle": "^7.8",
+    "monolog/monolog": "^2.9"
   },
   "autoload": {
     "psr-4": {

+ 82 - 82
rpc/tulip/tulip/content_download.php

@@ -4,74 +4,74 @@ require dirname(__FILE__) . '/config.php';
 require dirname(__FILE__) . '/logger.php';
 require dirname(__FILE__) . '/pdo.php';
 
-logger('debug','download full test search content start');
+logger('debug', 'download full test search content start');
 $param = getopt('b:');
 
-if(isset($param['b'])){
+if (isset($param['b'])) {
     $bookId = (int)$param['b'];
-    logger('debug','update book='.$bookId);
+    logger('debug', 'update book=' . $bookId);
 }
 $PDO = new PdoHelper;
 
 $PDO->connectDb();
-logger('debug','connect database finished');
+logger('debug', 'connect database finished');
 
 $client = new GuzzleHttp\Client();
 
 $pageSize = 1000;
 
-    $urlBase = Config['api_server'] . '/v2/pali-search-data';
-    logger('debug','url='.$urlBase);
-    if(isset($bookId)){
-        $from = $bookId;
-        $to = $bookId;
-    }else{
-        $from = 1;
-        $to = 217; 
-    }
-    for ($book=$from; $book <= $to; $book++) { 
-        $currPage = 1;
-        $urlBook = $urlBase . "?book={$book}";
-        logger('debug','fetch book='.$book);
-        do {
-            $goNext = false;
-            $url = $urlBook . "&start={$currPage}&page_size={$pageSize}";
-            logger('debug','url='.$url);
-            $res = $client->request('GET', $url);
-            $status = $res->getStatusCode();
-            if($status === 200){
-                $json = json_decode($res->getBody());
-                if($json->ok){
-                    $content = $json->data->rows;
-                    foreach ($json->data->rows as $row) {
-                        $book = $row->book;
-                        $paragraph = $row->paragraph;
-                        logger('debug',"update start book={$book} para={$paragraph} ");
-                        $now = date("Y-m-d H:i:s");
-                        //查询是否存在
-                        $query = 'SELECT id from fts_texts where book=? and paragraph = ?';
-                        $result = $PDO->dbSelect($query, [$book,$paragraph]);
-                        if(count($result) >0 ){
-                            //存在 update
-                            $query = 'UPDATE fts_texts set 
+$urlBase = Config['api_server'] . '/v2/pali-search-data';
+logger('debug', 'url=' . $urlBase);
+if (isset($bookId)) {
+    $from = $bookId;
+    $to = $bookId;
+} else {
+    $from = 1;
+    $to = 217;
+}
+for ($book = $from; $book <= $to; $book++) {
+    $currPage = 1;
+    $urlBook = $urlBase . "?book={$book}";
+    logger('debug', 'fetch book=' . $book);
+    do {
+        $goNext = false;
+        $url = $urlBook . "&start={$currPage}&page_size={$pageSize}";
+        logger('debug', 'url=' . $url);
+        $res = $client->request('GET', $url);
+        $status = $res->getStatusCode();
+        if ($status === 200) {
+            $json = json_decode($res->getBody());
+            if ($json->ok) {
+                $content = $json->data->rows;
+                foreach ($json->data->rows as $row) {
+                    $book = $row->book;
+                    $paragraph = $row->paragraph;
+                    logger('debug', "update start book={$book} para={$paragraph} ");
+                    $now = date("Y-m-d H:i:s");
+                    //查询是否存在
+                    $query = 'SELECT id from fts_texts where book=? and paragraph = ?';
+                    $result = $PDO->dbSelect($query, [$book, $paragraph]);
+                    if (count($result) > 0) {
+                        //存在 update
+                        $query = 'UPDATE fts_texts set 
                                                 "bold_single"=?,
                                                 "bold_double"=?,
                                                 "bold_multiple"=?,
                                                 "content"=?,
                                                 "pcd_book_id"=?,
                                                 "updated_at"=?  where id=? ';
-                            $update = $PDO->dbSelect($query, [
-                                                $row->bold1,
-                                                $row->bold2,
-                                                $row->bold3,
-                                                $row->content,
-                                                $row->pcd_book_id,
-                                                $now,
-                                                $result[0]['id']
-                                                    ]);
-                        }else{
-                            // new
-                            $query = "INSERT INTO fts_texts (
+                        $update = $PDO->dbSelect($query, [
+                            $row->bold1,
+                            $row->bold2,
+                            $row->bold3,
+                            $row->content,
+                            $row->pcd_book_id,
+                            $now,
+                            $result[0]['id']
+                        ]);
+                    } else {
+                        // new
+                        $query = "INSERT INTO fts_texts (
                                         book,
                                         paragraph,
                                         bold_single,
@@ -82,39 +82,39 @@ $pageSize = 1000;
                                         updated_at,
                                         pcd_book_id) VALUES
                                             (?,?,?,?,?,?,?,?,? )";
-                            $insert = $PDO->dbSelect($query, 
-                                            [
-                                                $row->book,
-                                                $row->paragraph,
-                                                $row->bold1,
-                                                $row->bold2,
-                                                $row->bold3,
-                                                $row->content,
-                                                $now,
-                                                $now,
-                                                $row->pcd_book_id,
-                                            ]);
-                        }
-                    }
-                    logger('debug',"update done book={$book} para={$paragraph} ");
-                    $maxPage = $json->data->count;
-                    logger('debug','max page ='.$maxPage);
-                    if($currPage+$pageSize<$maxPage){
-                        $goNext = true;
-                    }else{
-                        logger('debug',"book {$book} is done");
-                        $goNext = false;
+                        $insert = $PDO->dbSelect(
+                            $query,
+                            [
+                                $row->book,
+                                $row->paragraph,
+                                $row->bold1,
+                                $row->bold2,
+                                $row->bold3,
+                                $row->content,
+                                $now,
+                                $now,
+                                $row->pcd_book_id,
+                            ]
+                        );
                     }
-                }else{
-                    logger('error');
                 }
-            }else{
-                logger('error', 'status='.$status);
+                logger('debug', "update done book={$book} para={$paragraph} ");
+                $maxPage = $json->data->count;
+                logger('debug', 'max page =' . $maxPage);
+                if ($currPage + $pageSize < $maxPage) {
+                    $goNext = true;
+                } else {
+                    logger('debug', "book {$book} is done");
+                    $goNext = false;
+                }
+            } else {
+                logger('error', '');
             }
-            $currPage += $pageSize;
-        } while ($goNext);        
-    }
-
-logger('debug','all done') ;
-
+        } else {
+            logger('error', 'status=' . $status);
+        }
+        $currPage += $pageSize;
+    } while ($goNext);
+}
 
+logger('debug', 'all done');

+ 3 - 0
rpc/tulip/tulip/logs/.gitignore

@@ -0,0 +1,3 @@
+*
+!.gitignore
+

+ 36 - 17
rpc/tulip/tulip/pdo.php

@@ -1,34 +1,53 @@
 <?php
+require dirname(__FILE__) . '/vendor/autoload.php';
 
-class PdoHelper {
+use Monolog\Logger;
+use Monolog\Handler\StreamHandler;
+
+class PdoHelper
+{
     private $_pdo = null;
-    public function connectDb(){
+    private $log = null;
+
+    public function __construct()
+    {
+        // create a log channel
+        $this->log = new Logger('tulip');
+        $this->log->pushHandler(new StreamHandler(__DIR__ . '/logs/tulip-' . date("Y-m-d") . '.log'));
+    }
+    public function connectDb()
+    {
         /**
          * 连接数据库
          */
         $db = Config['database']['driver'];
-        $db .= ":host=".Config['database']['host'];
-        $db .= ";port=".Config['database']['port'];
-        $db .= ";dbname=".Config['database']['name'];
-        $db .= ";user=".Config['database']['user'];
-        $db .= ";password=".Config['database']['password'].";";
-        echo 'connect to db host='.Config['database']['host'] . ' name='.Config['database']['name'].PHP_EOL;
+        $db .= ":host=" . Config['database']['host'];
+        $db .= ";port=" . Config['database']['port'];
+        $db .= ";dbname=" . Config['database']['name'];
+        $db .= ";user=" . Config['database']['user'];
+        $db .= ";password=" . Config['database']['password'] . ";";
+
+        echo 'connect to db host=' . Config['database']['host'] . ' name=' . Config['database']['name'] . PHP_EOL;
         try {
-            $PDO = new PDO($db,
-                        Config['database']['user'],
-                        Config['database']['password'],
-                        array(PDO::ATTR_PERSISTENT=>true));
-        }catch(PDOException $e) {
-            echo 'connect to db fail'.PHP_EOL;
+            $PDO = new PDO(
+                $db,
+                Config['database']['user'],
+                Config['database']['password'],
+                array(PDO::ATTR_PERSISTENT => true)
+            );
+            $this->log->info('connect to db success');
+        } catch (PDOException $e) {
+            echo 'connect to db fail' . PHP_EOL;
             print $e->getMessage();
+            $this->log->error('connect to db fail');
             return false;
         }
         $PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
         $this->_pdo = $PDO;
     }
-    public function dbSelect($query, $params=null)
+    public function dbSelect($query, $params = null)
     {
-        if($this->_pdo === null){
+        if ($this->_pdo === null) {
             return false;
         }
         if (isset($params)) {
@@ -39,7 +58,7 @@ class PdoHelper {
         }
         return $stmt->fetchAll(PDO::FETCH_ASSOC);
     }
-    public function execute($query, $params=null)
+    public function execute($query, $params = null)
     {
         if (isset($params)) {
             $stmt = $this->_pdo->prepare($query);

+ 106 - 240
rpc/tulip/tulip/server.php

@@ -1,76 +1,22 @@
 <?php
 
-require dirname(__FILE__) . '/vendor/autoload.php';
-require dirname(__FILE__) . '/config.php';
-
+require_once dirname(__FILE__) . '/vendor/autoload.php';
+require_once dirname(__FILE__) . '/config.php';
+require_once dirname(__FILE__) . '/logger.php';
+require_once dirname(__FILE__) . '/pdo.php';
 
+use Monolog\Logger;
+use Monolog\Handler\StreamHandler;
 
 class Greeter extends \Mint\Tulip\V1\SearchStub
 {
-    private $_pdo = null;
-    private function log($level,$message){
-        $output = "[\033[32m".date("Y/m/d h:i:sa") ."\033[0m] ";
-        if($level === 'error'){
-            $output .= "\033[41m" . $level . "\033[0m ";
-        }else{
-            $output .= $level;
-        }
-        
-        $output .= ' ' . $message.PHP_EOL;
-        if($level === 'error'){
-            fwrite(STDERR,$output);
-        }else{
-            fwrite(STDOUT,$output);
-        }
-    }
-    private function connectDb(){
-        /**
-         * 连接数据库
-         */
-        $db = Config['database']['driver'];
-        $db .= ":host=".Config['database']['host'];
-        $db .= ";port=".Config['database']['port'];
-        $db .= ";dbname=".Config['database']['name'];
-        $db .= ";user=".Config['database']['user'];
-        $db .= ";password=".Config['database']['password'].";";
-        echo 'connect to db host='.Config['database']['host'] . ' name='.Config['database']['name'].PHP_EOL;
-        try {
-            $PDO = new PDO($db,
-                        Config['database']['user'],
-                        Config['database']['password'],
-                        array(PDO::ATTR_PERSISTENT=>true));
-        }catch(PDOException $e) {
-            echo 'connect to db fail'.PHP_EOL;
-            print $e->getMessage();
-            return false;
-        }
-        $PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-        $this->_pdo = $PDO;
-    }
-    private function dbSelect($query, $params=null)
-    {
-        if($this->_pdo === null){
-            return false;
-        }
-        if (isset($params)) {
-            $stmt = $this->_pdo->prepare($query);
-            $stmt->execute($params);
-        } else {
-            $stmt = $this->_pdo->query($query);
-        }
-        return $stmt->fetchAll(PDO::FETCH_ASSOC);
-    }
-
-        /**
-     * Create a new instance.
-     *
-     * @return void
-     */
+    private $log = null;
     public function __construct()
     {
-        $this->connectDb();
+        // create a log channel
+        $this->log = new Logger('tulip');
+        $this->log->pushHandler(new StreamHandler(__DIR__ . '/logs/tulip-' . date("Y-m-d") . '.log'));
     }
-
     public function Pali(
         \Mint\Tulip\V1\SearchRequest $request,
         \Grpc\ServerContext $context
@@ -79,30 +25,32 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
         foreach ($request->getKeywords()->getIterator() as $word) {
             $keyWords[] = $word;
         }
-        echo "[".date("Y/m/d h:i:sa") ."] pali search: request words = ".implode(',',$keyWords) .PHP_EOL;
+        $msg = "[" . date("Y/m/d h:i:sa") . "] pali search: request words = " . implode(',', $keyWords);
+        echo  $msg . PHP_EOL;
+        $this->log->info($msg);
 
+        $pdo = new PdoHelper;
+        $pdo->connectDb();
         /**
          * 查询业务逻辑
          */
 
-        $searchChapters = [];
-        $searchBooks = [];
-        $searchBookId = [];
         $bookId = [];
-        if($request->getBooks()->count()>0){
+        if ($request->getBooks()->count() > 0) {
             foreach ($request->getBooks()->getIterator() as $book) {
                 $bookId[] = $book;
             }
-            $queryBookId = ' AND pcd_book_id in ('.implode(',',$bookId).') ';
-        }else{
+            $queryBookId = ' AND pcd_book_id in (' . implode(',', $bookId) . ') ';
+        } else {
             $queryBookId = '';
         }
-        echo 'query books = '.implode(',',$bookId).PHP_EOL;
+        $msg = 'query books = ' . implode(',', $bookId);
+        echo  $msg . PHP_EOL;
+        $this->log->info($msg);
 
         $matchMode = $request->getMatchMode();
-        echo 'query mode = '.$matchMode.PHP_EOL;
+        echo 'query mode = ' . $matchMode . PHP_EOL;
         $param = [];
-        $countParam = [];
         switch ($matchMode) {
             case 'complete':
             case 'case':
@@ -110,18 +58,23 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
                 $querySelect_rank_base = " ts_rank('{0.1, 1, 0.3, 0.2}',
                                                 full_text_search_weighted,
                                                 websearch_to_tsquery('pali', ?)) ";
-                $querySelect_rank_head = implode('+', 
-                                            array_fill(0, count($keyWords), 
-                                            $querySelect_rank_base));
+                $querySelect_rank_head = implode(
+                    '+',
+                    array_fill(
+                        0,
+                        count($keyWords),
+                        $querySelect_rank_base
+                    )
+                );
 
-                $param = array_merge($param,$keyWords);
+                $param = array_merge($param, $keyWords);
                 $querySelect_rank = " {$querySelect_rank_head} AS rank, ";
                 $querySelect_highlight = " ts_headline('pali', content,
                                             websearch_to_tsquery('pali', ?),
                                             'StartSel = ~~, StopSel = ~~,MaxWords=3500, 
                                             MinWords=3500,HighlightAll=TRUE')
                                             AS highlight,";
-                array_push($param,implode(' ',$keyWords));
+                array_push($param, implode(' ', $keyWords));
                 break;
             case 'similar':
                 # 形似,去掉变音符号
@@ -131,7 +84,7 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
                         full_text_search_weighted_unaccent,
                         websearch_to_tsquery('pali_unaccent', ?))
                     AS rank, ";
-                    $param[] = $key;
+                $param[] = $key;
                 $querySelect_highlight = " ts_headline('pali_unaccent', content,
                         websearch_to_tsquery('pali_unaccent', ?),
                         'StartSel = ~~, StopSel = ~~,
@@ -141,20 +94,30 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
                 $param[] = $key;
                 break;
         }
-        $_queryWhere = $this->makeQueryWhere($keyWords,$matchMode);
+        $_queryWhere = $this->makeQueryWhere($keyWords, $matchMode);
         $queryWhere = $_queryWhere['query'];
-        $param = array_merge($param,$_queryWhere['param']);
+        $param = array_merge($param, $_queryWhere['param']);
 
         $querySelect_2 = "  book,paragraph,content ";
 
         $queryCount = "SELECT count(*) as co FROM fts_texts WHERE {$queryWhere} {$queryBookId};";
-        $resultCount = $this->dbSelect($queryCount, $_queryWhere['param']);
-        $total = $resultCount[0]['co'];
+        $resultCount = $pdo->dbSelect($queryCount, $_queryWhere['param']);
+        if (
+            is_array($resultCount) &&
+            count($resultCount) > 0 &&
+            isset($resultCount[0]['co'])
+        ) {
+            $total = $resultCount[0]['co'];
+        } else {
+            logger('warning', 'result must be of type array' . $pdo->errorInfo());
+            $this->log->error('result must be of type array' . $pdo->errorInfo());
+            $total = 0;
+        }
 
-        if($request->hasPage()){
+        if ($request->hasPage()) {
             $limit = $request->getPage()->getSize();
             $offset = $request->getPage()->getIndex();
-        }else{
+        } else {
             $limit = 10;
             $offset = 0;
         }
@@ -183,21 +146,25 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
         $param[] = $limit;
         $param[] = $offset;
 
-        $result = $this->dbSelect($query, $param);
-
-         //返回数据
+        $result = $pdo->dbSelect($query, $param);
+        //返回数据
         $response = new \Mint\Tulip\V1\SearchResponse();
         $output = $response->getItems();
-        foreach ($result as $row) {
-            $item = new \Mint\Tulip\V1\SearchResponse\Item;
-            $item->setRank($row['rank']);
-            $item->setHighlight($row['highlight']);
-            $item->setBook($row['book']);
-            $item->setParagraph($row['paragraph']);
-            $item->setContent($row['content']);
-            $output[] = $item;
+
+        if ($result) {
+            foreach ($result as $row) {
+                $item = new \Mint\Tulip\V1\SearchResponse\Item;
+                $item->setRank($row['rank']);
+                $item->setHighlight($row['highlight']);
+                $item->setBook($row['book']);
+                $item->setParagraph($row['paragraph']);
+                $item->setContent($row['content']);
+                $output[] = $item;
+            }
         }
-        echo "total={$total}".PHP_EOL;
+
+        echo "total={$total}" . PHP_EOL;
+        $this->log->info("total={$total}");
         $response->setTotal($total);
         return $response;
     }
@@ -216,155 +183,48 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
         foreach ($request->getKeywords()->getIterator() as $word) {
             $keyWords[] = $word;
         }
-        echo "book list: request words = ".implode(',',$keyWords) .PHP_EOL;
+        echo "book list: request words = " . implode(',', $keyWords) . PHP_EOL;
         /**
          * 查询业务逻辑
          */
+        $pdo = new PdoHelper;
+        $pdo->connectDb();
 
-         $searchChapters = [];
-         $searchBooks = [];
-         $searchBookId = [];
-         $bookId = [];
-         if($request->getBooks()->count()>0){
-             foreach ($request->getBooks()->getIterator() as $book) {
-                 $bookId[] = $book;
-             }
-             $queryBookId = ' AND pcd_book_id in ('.implode(',',$bookId).') ';
-         }else{
-             $queryBookId = '';
-         }
-         echo 'query books = '.implode(',',$bookId).PHP_EOL;
- 
-         $matchMode = $request->getMatchMode();
-         echo 'query mode = '.$matchMode.PHP_EOL;
-         $queryWhere = $this->makeQueryWhere($keyWords,$matchMode);
-         $query = "SELECT pcd_book_id, count(*) as co FROM fts_texts WHERE {$queryWhere['query']} {$queryBookId} GROUP BY pcd_book_id ORDER BY co DESC;";
-         $result = $this->dbSelect($query, $queryWhere['param']);
-         //返回数据
-         $response = new \Mint\Tulip\V1\BookListResponse();
-         $output = $response->getItems();
-         foreach ($result as $row) {
-             $item = new \Mint\Tulip\V1\BookListResponse\Item;
-             $item->setBook($row['pcd_book_id']);
-             $item->setCount($row['co']);
-             $output[] = $item;
-         }
-         echo "total=".count($output).PHP_EOL;
-         return $response;
-    }
-    /**
-     * @param \Mint\Tulip\V1\UploadDictionaryRequest $request client request
-     * @param \Grpc\ServerContext $context server request context
-     * @return \Mint\Tulip\V1\UploadDictionaryResponse for response data, null if if error occured
-     *     initial metadata (if any) and status (if not ok) should be set to $context
-     */
-    public function UploadDictionary(
-        \Mint\Tulip\V1\UploadDictionaryRequest $request,
-        \Grpc\ServerContext $context
-    ): ?\Mint\Tulip\V1\UploadDictionaryResponse {
-        $response = new \Mint\Tulip\V1\UploadDictionaryResponse();
-        $data = $request->getData();
-        $this->log('debug',"received data size=".strlen($data));
-        $dir = dirname(__FILE__) . '/storage';
-        if(!is_dir($dir)){
-            $res = mkdir($dir,0700,true);
-            if(!$res){
-                $this->log('error',"mkdir fail path=".$dir);
-                $response->setError(1);
-                return $response;
+        $bookId = [];
+        if ($request->getBooks()->count() > 0) {
+            foreach ($request->getBooks()->getIterator() as $book) {
+                $bookId[] = $book;
             }
+            $queryBookId = ' AND pcd_book_id in (' . implode(',', $bookId) . ') ';
+        } else {
+            $queryBookId = '';
         }
-        $filename = $dir.'/pali-'.date("Y-m-d-h-i-sa").'.syn';
-        $size = file_put_contents($filename,$data);
-
-        if($size === false){
-            $this->log('error',"file write fail ");
-            $response->setError(1);
-            return $response;
-        }
-        $this->log('debug',"save file size={$size} ");
-        $response->setError(0);
-        return $response;
-    }
+        echo 'query books = ' . implode(',', $bookId) . PHP_EOL;
 
-    public function Update(
-        \Mint\Tulip\V1\UpdateRequest $request,
-        \Grpc\ServerContext $context
-    ): ?\Mint\Tulip\V1\UpdateResponse {
-        $response = new \Mint\Tulip\V1\UpdateResponse();
-        $book = $request->getBook();
-        $paragraph = $request->getParagraph();
-        $this->log('debug',"update start book={$book} para={$paragraph} ");
-        $now = date("Y-m-d H:i:s");
-        //查询是否存在
-        $query = 'SELECT id from fts_texts where book=? and paragraph = ?';
-        $result = $this->dbSelect($query, [$book,$paragraph]);
-        if(count($result) >0 ){
-            //存在 update
-            $query = 'UPDATE fts_texts set 
-                                "bold_single"=?,
-                                "bold_double"=?,
-                                "bold_multiple"=?,
-                                "content"=?,
-                                "pcd_book_id"=?,
-                                "updated_at"=?  where id=? ';
-            $update = $this->dbSelect($query, [
-                                $request->getBold1(),
-                                $request->getBold2(),
-                                $request->getBold3(),
-                                $request->getContent(),
-                                $request->getPcdBookId(),
-                                $now,
-                                $result[0]['id']
-                                    ]);
-        }else{
-            // new
-            $query = "INSERT INTO fts_texts (
-                        book,
-                        paragraph,
-                        bold_single,
-                        bold_double,
-                        bold_multiple,
-                        \"content\",
-                        created_at,
-                        updated_at,
-                        pcd_book_id) VALUES
-            (?,?,?,?,?,?,?,?,? )";
-            $insert = $this->dbSelect($query, [
-                            $request->getBook(),
-                            $request->getParagraph(),
-                            $request->getBold1(),
-                            $request->getBold2(),
-                            $request->getBold3(),
-                            $request->getContent(),
-                            $now,
-                            $now,
-                            $request->getPcdBookId(),
-                                ]);
+        $matchMode = $request->getMatchMode();
+        echo 'query mode = ' . $matchMode . PHP_EOL;
+        $queryWhere = $this->makeQueryWhere($keyWords, $matchMode);
+        $query = "SELECT pcd_book_id, count(*) as co FROM fts_texts WHERE {$queryWhere['query']} {$queryBookId} GROUP BY pcd_book_id ORDER BY co DESC;";
+        $result = $pdo->dbSelect($query, $queryWhere['param']);
+        //返回数据
+        $response = new \Mint\Tulip\V1\BookListResponse();
+        $output = $response->getItems();
+        if ($result) {
+            foreach ($result as $row) {
+                $item = new \Mint\Tulip\V1\BookListResponse\Item;
+                $item->setBook($row['pcd_book_id']);
+                $item->setCount($row['co']);
+                $output[] = $item;
+            }
         }
 
-        $response->setCount(0);
+        echo "total=" . count($output) . PHP_EOL;
         return $response;
     }
 
-    private function _updateIndex($book,$para){
-        $query = 'UPDATE fts_texts SET content = content,
-        bold_single = bold_single,
-        bold_double = bold_double,
-        bold_multiple = bold_multiple
-        WHERE book = ? AND paragraph = ?';
-        $update = $this->dbSelect($query, [$book,$para]);
-    }
-    
-    private function _updateIndexAll(){
-        $query = 'UPDATE fts_texts SET content = content,
-        bold_single = bold_single,
-        bold_double = bold_double,
-        bold_multiple = bold_multiple';
-        $update = $this->dbSelect($query);
-    }
 
-    private function makeQueryWhere($key,$match){
+    private function makeQueryWhere($key, $match)
+    {
         $param = [];
         $queryWhere = '';
         switch ($match) {
@@ -372,10 +232,13 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
             case 'case':
                 # code...
                 $queryWhereBase = " full_text_search_weighted @@ websearch_to_tsquery('pali', ?) ";
-                $queryWhereBody = implode(' or ', array_fill(0, count($key), 
-                                    $queryWhereBase));
+                $queryWhereBody = implode(' or ', array_fill(
+                    0,
+                    count($key),
+                    $queryWhereBase
+                ));
                 $queryWhere = " ({$queryWhereBody}) ";
-                $param = array_merge($param,$key);
+                $param = array_merge($param, $key);
                 break;
             case 'similar':
                 # 形似,去掉变音符号
@@ -384,13 +247,16 @@ class Greeter extends \Mint\Tulip\V1\SearchStub
                 $param = [$key];
                 break;
         };
-        return (['query'=>$queryWhere,'param'=>$param]);
+        return (['query' => $queryWhere, 'param' => $param]);
     }
 
     private function getWordEn($strIn)
     {
-        $out = str_replace(["ā","ī","ū","ṅ","ñ","ṭ","ḍ","ṇ","ḷ","ṃ"],
-                        ["a","i","u","n","n","t","d","n","l","m"], $strIn);
+        $out = str_replace(
+            ["ā", "ī", "ū", "ṅ", "ñ", "ṭ", "ḍ", "ṇ", "ḷ", "ṃ"],
+            ["a", "i", "u", "n", "n", "t", "d", "n", "l", "m"],
+            $strIn
+        );
         return ($out);
     }
 }