From bf1a0d61c51c6fd713ea89c57d0855de468b36c8 Mon Sep 17 00:00:00 2001 From: wlx Date: Sun, 16 Dec 2012 08:40:08 +0000 Subject: [PATCH] =?UTF-8?q?#217,=20=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0xun?= =?UTF-8?q?search=E7=9A=84=E9=9B=86=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/controllers/SearchController.php | 38 +++ .../default/views/scripts/search/index.phtml | 209 +++++++++++++++++ .../views/scripts/search/index.phtml.save | 198 ++++++++++++++++ application/models/Search.php | 220 +++++++++++++++++- 4 files changed, 658 insertions(+), 7 deletions(-) create mode 100644 application/default/controllers/SearchController.php create mode 100644 application/default/views/scripts/search/index.phtml create mode 100644 application/default/views/scripts/search/index.phtml.save diff --git a/application/default/controllers/SearchController.php b/application/default/controllers/SearchController.php new file mode 100644 index 00000000..bc3e8f68 --- /dev/null +++ b/application/default/controllers/SearchController.php @@ -0,0 +1,38 @@ +db=Zend_Registry::get('db'); + $this->view->config = Zend_Registry::get('config'); + $this->messenger=$this->_helper->getHelper('FlashMessenger'); + $this->view->messages = $this->messenger->getMessages(); + } + + function indexAction() + { + $search=new Search(); + $search->dosearch(); + $this->view->hot=$search->hot; + $this->view->total_cost=$search->total_cost; + $this->view->count=$search->count; + $this->view->base_url=$search->base_url; + $this->view->error=$search->error; + $this->view->docs=$search->docs; + $this->view->search=$search->search; + $this->view->related=$search->related; + $this->view->pager=$search->pager; + $this->view->total=$search->total; + $this->view->expanded=$search->expanded; + } + function suggestAction() + { + $q = isset($_GET['term']) ? trim($_GET['term']) : ''; + $q = get_magic_quotes_gpc() ? stripslashes($q) : $q; + $search=new Search(); + $this->_helper->layout->disableLayout(); + $this->_helper->viewRenderer->setNoRender(); + header("Content-Type: application/json; charset=utf-8"); + echo $search->suggest($q); + } +} diff --git a/application/default/views/scripts/search/index.phtml b/application/default/views/scripts/search/index.phtml new file mode 100644 index 00000000..33eb139c --- /dev/null +++ b/application/default/views/scripts/search/index.phtml @@ -0,0 +1,209 @@ +search; + + $this->headTitle($this->config->title->site); + $this->headTitle('首页'); + $this->headTitle('搜索'); + $this->headTitle()->setSeparator(' - '); + $this->headLink()->appendStylesheet('/css/search.css'); + ?> + +
+ + +
+
+ + +
+
+

选项

+
    +
  • />Title
  • +
  • />全文
  • +
  • />模糊搜索
  • +
  • />同义词
  • +
  • + 按 + + 排序 +
  • +
+
+
+ + + hot) > 0): ?> + + + + + + + +
+ 大约有 count); ?> 项符合查询结果, + 库内数据总量为 total); ?> 项。 + (搜索耗时:search_cost); ?>秒 - 页面处理时间:total_cost); ?>秒) + [base_url&xml=yes&p=$p" ;?> " target="_blank">XML] +
+ + + error)): ?> +
错误:error; ?>
+ + + + corrected) > 0): ?> +
+

您是不是要找:

+
    + corrected as $word): ?> +
  • + +
+
+ + + expanded) > 0): ?> +
+

您是不是要找:

+
    + expanded as $word): ?> +
  • + +
+
+ + + + + count === 0 && empty($this->error)): ?> +
+

找不到和 相符的内容或信息。建议您:

+
    +
  • 请检查输入字词有无错误。
  • +
  • 请换用另外的查询字词。
  • +
  • 请改用较短、较为常见的字词。
  • +
+
+ + + +
+ docs as $doc): ?> +
+

+ rank(); ?>. search->highlight(htmlspecialchars($doc->title)); ?> + [percent(); ?>%] +

+

highlight(htmlspecialchars($doc->description)); ?>

+
    +
  • metadata: highlight(htmlspecialchars($doc->data)); ?>
  • +
+
+ +
+ + + pager)): ?> +
+ 分页: + pager; ?> +
+ + + + related) > 0): ?> + + + + + + +
+ + + + + + + + diff --git a/application/default/views/scripts/search/index.phtml.save b/application/default/views/scripts/search/index.phtml.save new file mode 100644 index 00000000..ff9ef961 --- /dev/null +++ b/application/default/views/scripts/search/index.phtml.save @@ -0,0 +1,198 @@ +search; + + $this->headTitle($this->config->title->site); + $this->headTitle('首页'); + $this->headTitle('搜索'); + $this->headTitle()->setSeparator(' - '); + $this->headLink()->appendStylesheet('/css/search.css'); + ?> + +
+ + +
+
+ + +
+
+

选项

+
    +
  • />Title
  • +
  • />全文
  • +
  • />模糊搜索
  • +
  • />同义词
  • +
  • + 按 + + 排序 +
  • +
+
+
+ + + hot) > 0): ?> + + + + + + + +
+ 大约有 count); ?> 项符合查询结果, + 库内数据总量为 total); ?> 项。 + (搜索耗时:search_cost); ?>秒 - 页面处理时间:total_cost); ?>秒) + [base_url&xml=yes&p=$p" ;?> " target="_blank">XML] +
+ + + error)): ?> +
错误:error; ?>
+ + + + + corrected) > 0): ?> +
+

您是不是要找:

+
    + corrected as $word): ?> +
  • + +
+
+ + + + count === 0 && empty($this->error)): ?> +
+

找不到和 相符的内容或信息。建议您:

+
    +
  • 请检查输入字词有无错误。
  • +
  • 请换用另外的查询字词。
  • +
  • 请改用较短、较为常见的字词。
  • +
+
+ + + +
+ docs as $doc): ?> +
+

+ rank(); ?>. search->highlight(htmlspecialchars($doc->title)); ?> + [percent(); ?>%] +

+

highlight(htmlspecialchars($doc->description)); ?>

+
    +
  • metadata: highlight(htmlspecialchars($doc->data)); ?>
  • +
+
+ +
+ + + pager)): ?> +
+ 分页: + pager; ?> +
+ + + + related) > 0): ?> + + + + + + +
+ + + + + + + + diff --git a/application/models/Search.php b/application/models/Search.php index cdc7cf4b..98410b46 100644 --- a/application/models/Search.php +++ b/application/models/Search.php @@ -3,12 +3,21 @@ class Search { var $terms; var $text; - - function Search($text) - { - $this->terms = array(); - $this->text=$text; - } + var $xs; + var $search; + var $error; + var $pager; + var $count; + var $related; + var $corrected; + var $total; + var $search_cost; + var $docs; + var $hot; + var $base_url; + var $expanded; + + //require_once '/home/wlx/xunsearch/sdk/php/lib/XS.php'; private function safe_query($search) { @@ -54,4 +63,201 @@ class Search } return $sql; } -} \ No newline at end of file + function __construct($text='') + { + require_once '/home/wlx/xunsearch/sdk/php/lib/XS.php'; + $this->xs=new XS('westdc'); + $this->search=$this->xs->search; + $this->terms = array(); + $this->text=$text; + + // other variable maybe used + $this->count = $this->total = $this->search_cost = 0; + $this->docs = $this->related = $this->corrected =$this->expanded = $this->hot = array(); + $this->error = $this->pager = $this->base_url=''; + } + + function dosearch() + { +// +// 支持的 GET 参数列表 +// q: 查询语句 +// m: 开启模糊搜索,其值为 yes/no +// f: 只搜索某个字段,其值为字段名称,要求该字段的索引方式为 self/both +// s: 排序字段名称及方式,其值形式为:xxx_ASC 或 xxx_DESC +// p: 显示第几页,每页数量为 XSSearch::PAGE_SIZE 即 10 条 +// ie: 查询语句编码,默认为 UTF-8 +// oe: 输出编码,默认为 UTF-8 +// xml: 是否将搜索结果以 XML 格式输出,其值为 yes/no +// +// variables +$eu = ''; +$__ = array('q', 'm', 'f', 's', 'p', 'ie', 'oe', 'syn', 'xml'); +foreach ($__ as $_) + $$_ = isset($_GET[$_]) ? $_GET[$_] : ''; + +// recheck request parameters +$q = get_magic_quotes_gpc() ? stripslashes($q) : $q; +$f = empty($f) ? '_all' : $f; +${'m_check'} = ($m == 'yes' ? ' checked' : ''); +${'syn_check'} = ($syn == 'yes' ? ' checked' : ''); +${'f_' . $f} = ' checked'; +${'s_' . $s} = ' selected'; +if (!isset($q)) $q=''; +// base url +$this->base_url = '/search?q=' . urlencode($q) . '&m=' . $m . '&f=' . $f . '&s=' . $s . $eu; + + +$total_begin = microtime(true); +// perform the search +try +{ + $this->search->setCharset('UTF-8'); + + if (empty($q)) + { + // just show hot query + $this->hot = $this->search->getHotQuery(); + } + else + { + // fuzzy search + $this->search->setFuzzy($m === 'yes'); + + // synonym search + $this->search->setAutoSynonyms($syn === 'yes'); + + // set query + if (!empty($f) && $f != '_all') + { + $this->search->setQuery($f . ':(' . $q . ')'); + } + else + { + $this->search->setQuery($q); + } + + // set sort + if (($pos = strrpos($s, '_')) !== false) + { + $sf = substr($s, 0, $pos); + $st = substr($s, $pos + 1); + $this->search->setSort($sf, $st === 'ASC'); + } + + // set offset, limit + $p = max(1, intval($p)); + $n = XSSearch::PAGE_SIZE; + $this->search->setLimit($n, ($p - 1) * $n); + + // get the result + $search_begin = microtime(true); + $this->docs = $this->search->search(); + $this->search_cost = microtime(true) - $search_begin; + + // get other result + $this->count = $this->search->getLastCount(); + $this->total = $this->search->getDbTotal(); + + if ($xml !== 'yes') + { +if ($this->count<1) + $this->expanded=$this->search->getExpandedQuery($q); + // try to corrected, if resul too few + if ($this->count < 1 || $this->count < ceil(0.001 * $this->total)) + $this->corrected = $this->search->getCorrectedQuery(); + // get related query + $this->related = $this->search->getRelatedQuery(); + } + + // gen pager + if ($this->count > $n) + { + $pb = max($p - 5, 1); + $pe = min($pb + 10, ceil($this->count / $n) + 1); + $this->pager = ''; + do + { + $this->pager .= ($pb == $p) ? '' . $p . '' : '[' . $pb . ']'; + } + while (++$pb < $pe); + } + } +} +catch (XSException $e) +{ + $this->error = strval($e); +} +// calculate total time cost +$this->total_cost = microtime(true) - $total_begin; + +// XML OUPUT +if ($xml === 'yes' && !empty($q)) +{ + header("Content-Type: text/xml; charset=$oe"); + echo "\n"; + echo "count\" total=\"$this->total\" cost=\"$this->total_cost\" xmlns:xs=\"http://www.xunsearch.com\">\n"; + if ($this->error !== '') + echo " error . "]]>\n"; + + foreach ($this->docs as $doc) + { + echo " rank() . "\" percent=\"" . $doc->percent() . "%\">\n"; + foreach ($doc as $k => $v) + { + echo " <$k>"; + if (is_numeric($v)) + echo $v; + else + echo "\n \n "; + echo "\n"; + } + echo " \n"; + } + echo "\n"; + exit(0); +} +} + //搜索建议 + function suggest($q) + { + $terms = array(); + if (!empty($q) && strpos($q, ':') === false) + { + try { + $terms = $this->search->setCharset('UTF-8')->getExpandedQuery($q); + } catch (XSException $e) { } + } + return json_encode($terms); + } + + //添加新文档 + //$data: 数组 + function add($data) + { + $doc=new XSDocument; + $index=$this->xs->index; + $doc->setFields($data); + $index->add($doc); + } + + //更新已有文档 + //$data: 数组 + function update($data) + { + $doc=new XSDocument; + $index=$this->xs->index; + $doc->setFields($data); + $index->update($doc); + } + //根据主键删除对应的索引 + function del($data,$field='') + { + $index=$this->xs->index; + if (empty($field)) + $index->del($data); + else { + $index->del($data,$field); + } + } +}