概述
typecho 自带的搜索方式不好用,不支持分词操作
解决
为了缩小索引力度,可以修改 mysql 配置
[mysqld]
innodb_ft_min_token_size = 2
ft_min_word_len = 2
ngram_token_size = 2
更多详情可以查看:https://www.xiaoqiuyinboke.cn/archives/913.html
然后先添加全文索引
CREATE FULLTEXT INDEX ft_index_title ON blog_contents (title) WITH PARSER ngram;
CREATE FULLTEXT INDEX ft_index_text ON blog_contents (text) WITH PARSER ngram;
然后修改 php 代码
var/Widget/Archive.php:759
位置,也就是 $this->countSql = clone $select;
下一行,增加
$this->countSql->cleanAttribute("order");
如下图所示:
最后修改 php 代码 searchHandle 方法
\Widget\Archive::searchHandle
方法里修改
private function searchHandle(Query $select, &$hasPushed)
{
/** 增加自定义搜索引擎接口 */
//~ fix issue 40
$keywords = $this->request->get('keywords');
//$keywords = $this->request->filter('url', 'search')->keywords;
self::pluginHandle()->trigger($hasPushed)->search($keywords, $this);
if (!$hasPushed) {
/** 搜索无法进入隐私项保护归档 */
if ($this->user->hasLogin()) {
//~ fix issue 941
$select->where("table.contents.password IS NULL
OR table.contents.password = '' OR table.contents.authorId = ?", $this->user->uid);
} else {
$select->where("table.contents.password IS NULL OR table.contents.password = ''");
}
// 修改这里
$select->select(
"*",
"MATCH(title)AGAINST('{$keywords}') AS score_title",
"MATCH(text)AGAINST('{$keywords}') AS score_text"
);
// 注释原来的
//$op = $this->db->getAdapter()->getDriver() == 'pgsql' ? 'ILIKE' : 'LIKE';
//
//$select->where("table.contents.title {$op} ? OR table.contents.text {$op} ?", $searchQuery, $searchQuery)
// ->where('table.contents.type = ?', 'post');
// 增加这个
$select->where('table.contents.password IS NULL')
->where("((MATCH(table.contents.title)AGAINST('{$keywords}')) OR (MATCH(table.contents.text)AGAINST('{$keywords}')))")
->where('table.contents.type = ?', 'post')
->order('score_title', Db::SORT_DESC)
->order('score_text', Db::SORT_DESC);
}
/** 设置关键词 */
$this->keywords = $keywords;
/** 设置分页 */
$this->pageRow = ['keywords' => urlencode($keywords)];
/** 设置头部feed */
/** RSS 2.0 */
$this->feedUrl = Router::url('search', ['keywords' => $keywords], $this->options->feedUrl);
/** RSS 1.0 */
$this->feedRssUrl = Router::url('search', ['keywords' => $keywords], $this->options->feedAtomUrl);
/** ATOM 1.0 */
$this->feedAtomUrl = Router::url('search', ['keywords' => $keywords], $this->options->feedAtomUrl);
/** 设置标题 */
$this->archiveTitle = $keywords;
/** 设置归档类型 */
$this->archiveType = 'search';
/** 设置归档缩略名 */
$this->archiveSlug = $keywords;
/** 设置归档地址 */
$this->archiveUrl = Router::url('search', ['keywords' => $keywords], $this->options->index);
/** 插件接口 */
self::pluginHandle()->searchHandle($this, $select);
}