搜索实现分词搜索功能
实现原理:
如 “装修二级” 拆分为 “装”“修”“二”“级”,只要目标内容包含这几个字即可匹配,无需考虑顺序和同义词。
找到搜索文件 /dayrui/App/Module/Models/Search.php
大约187行 注释掉下面这个代码
// 关键字匹配条件
if ($param['keyword'] != '') {
$temp = [];
$sfield = explode(',', $this->module['setting']['search']['field'] ? $this->module['setting']['search']['field'] : 'title,keywords');
$search_keyword = explode('|', addslashes((string)$param['keyword']));
foreach ($search_keyword as $kw) {
$is = 0;
if ($sfield) {
foreach ($sfield as $t) {
if ($t && dr_in_array($t, $field)) {
$is = 1;
$temp[] = $this->module['setting']['search']['complete'] ? '`'.$table.'`.`'.$t.'` = \''.$kw.'\'' : '`'.$table.'`.`'.$t.'` LIKE \'%'.$kw.'%\'';
}
}
}
if (!$is) {
$temp[] = $this->module['setting']['search']['complete'] ? '`'.$table.'`.`title` = \''.$kw.'\'' : '`'.$table.'`.`title` LIKE \'%'.$kw.'%\'';
}
}
$where['keyword'] = $temp ? '('.implode(' OR ', $temp).')' : '';
$param_new['keyword'] = $search_keyword;
}然后下面增加
// 关键字匹配条件(分词搜索:拆分单个字符,匹配所有字符)
if ($param['keyword'] != '') {
$temp = [];
$sfield = explode(',', $this->module['setting']['search']['field'] ? $this->module['setting']['search']['field'] : 'title,keywords');
$original_kw = addslashes((string)$param['keyword']);
// 拆分关键词为单个字符(支持汉字)
$chars = [];
$length = mb_strlen($original_kw, 'UTF-8');
for ($i = 0; $i < $length; $i++) {
$char = mb_substr($original_kw, $i, 1, 'UTF-8');
// 过滤空字符和特殊符号
if ($char && preg_match('/[\p{Han}\d]/u', $char)) {
$chars[] = $char;
}
}
// 如果有有效字符则构建条件
if (!empty($chars)) {
foreach ($chars as $char) {
$char_conditions = [];
// 对每个搜索字段添加包含当前字符的条件
if ($sfield) {
foreach ($sfield as $t) {
if ($t && dr_in_array($t, $field)) {
$char_conditions[] = '`'.$table.'`.`'.$t.'` LIKE \'%'.$char.'%\'';
}
}
}
// 如果没有指定字段,默认用title
if (empty($char_conditions)) {
$char_conditions[] = '`'.$table.'`.`title` LIKE \'%'.$char.'%\'';
}
// 每个字符必须至少匹配一个字段(用OR连接字段,用AND连接不同字符)
$temp[] = '('.implode(' OR ', $char_conditions).')';
}
// 所有字符条件用AND连接(必须包含所有字符)
$where['keyword'] = $temp ? '('.implode(' AND ', $temp).')' : '';
}
$param_new['keyword'] = $original_kw;
}既可以实现分词搜索。