mysql支持中文全文检索的实现方法

作者:袖梨 2022-11-14

mysql教程支持中文全文检索的实现方法

不影响 MySQL 的系统结构及其他功能的前提下,解决了 MySQL 目前对中文全文检索无法正确支持的缺陷并优化 MySQL 对中文检索处理的性能。(目前本软件包支持根据词典进行简易的正向最大匹配分词、支持包括UTF-8、GBK、BIG5 ... 在内的字符集)

经测试效果尚可, 140万行约 1.4G 数据(不含索引区空间) 检索大概都在 0.0x ~ 0.x 秒之间. 搭配做一个小型全文检索将变得十分简单.

MySQL 从 3.23 的某个小版本开始就已经支持在 MyISAM 表中建立全文索引的字段。由于 CJK(中日韩)字符集及其句法的特殊性(词与词之间没有像英文一样的间隔),MySQL 一直没有针对多字节的宽字符集作出应有的支持,也没有任何分词能力。

而 MySQL 作为 PHP 等 Web Script 的绝佳搭档,已经被广泛应用到各个角落,对于它的检索令绝大多数开发者头痛,用 SELECT ... WHERE ... LIKE %...% 的方式不仅效率差(动则扫描全表岂能不慢?),对于中文这样的特殊语言也存在严重的岐义问题(因为词才是最小的语意单位)。我也在一段时间内受限于 MySQL 的检索限制,而不得不寻求其它解决方案,但都不太尽人意。

--
顺便提一下,有一个叫作海量的分词技术公司,很早就做过 mysql-chinese 的 hack,只不过迟迟没有按照 GNU 精神及时发布源码,所以才决定自己来作。

-- 用 PHP 配合 MySQL (4.0.x) 的全文检索例子代码 --

if ($_GET['q'] && $q = trim($_GET['q']))
{
mysql_connect();
mysql_select_db("dot66");
$q = mysql_escape_string($q);
$r = mysql_query("SELECT SEGMENT('$q')");
$n = mysql_fetch_row($r);
$x = explode(" ", $n[0]);
$m = $str = '';
$f = $t = array();
foreach ($x as $tmp)
{
if (strlen($tmp) > strlen($m)) $m = $tmp;
$f[] = "/($tmp)/i";
$t[] = '1';
}
$s1 = "SELECT id,board,owner,chrono,title,SUBSTRING(body,LOCATE('$m', body)-50,200) AS xbody ";
$s2 = "FROM bbs_posts WHERE MATCH(title,body) AGAINST ('$q'";
$s2 .= (preg_match('/[<>()~*"+-]/', $q) ? ' IN BOOLEAN MODE' : '');
$s2 .= ") LIMIT 100";

$r = mysql_query("SELECT COUNT(*) $s2");
$x = mysql_fetch_row($r);
$x = $x[0];
$s = $s1 . $s2;
echo '

The Core SQL Query String:
' . $s . '

';
$r = mysql_query($s);
while ($tmp = mysql_fetch_assoc($r))
{
if (($pos = strpos($tmp['owner'], '.')) || ($pos = strpos($tmp['owner'], '@')))
$tmp['owner'] = substr($tmp['owner'],0,$pos).'.';
$str .= "
  • $tmp[title] (看板: $tmp[board])
    n";
    $str .= " ... $tmp[xbody] ...
    n";
    $str .= "Author: $tmp[owner] Date: " . date("Y-m-d H:i", $tmp['chrono']) . "n";
    $str .= "


  • n";
    }
    $f[] = '/x1b[.*?m/';
    $t[] = '';
    $str = preg_replace($f, $t, $str);
    }
    mysql_close();
    }
    ?>
    BBS(看板检索: powered by MySQL fulltext+)

    BBS(看板检索: powered by MySQL fulltext+)






    (随便输入字符串检索, 还可以用简单的 +/- 哦, 收录约有 140万篇文章)




    这是一个朋友自己做的

    业界评论海量科技的分词技术目前被认为是国内最好的中文分词技术,其分词准确度超过99%,由此也使得中搜在搜索结果中搜索结果的错误率很低。

    海量http://www.hylanda.com/server/
    下载MySQL5.0.37--LinuxX86-Chinese+
    不需要提前安装mysql 然后依次执行
    groupadd mysql
    useradd -g mysql mysql
    cd /usr/local
    gunzip < /root/mysql-chplus-5.0.37-linux-i686.tar.gz|tar xvf -
    ln -s /usr/local/mysql-chplus-5.0.37 /usr/local/mysql
    cd mysql
    scritps教程/mysql_install_db --user=mysql
    chown -R mysql data
    chown -R mysql .
    /usr/local/mysql/bin/mysqld_safe --user=mysql &
    即可 测试:
    create table test ( testid int(4) not null , testtitle varchar(256), testbody varchar(256), fulltext(testtitle,testbody));
    insert into test values
    ->(NULL,'你好吗','特斯他你好吗'),
    ->(NULL,'好你好','好你好');
    select * from test where match(testtitle,testbody) against('你好' in boolean mode);


    Hightman的 scws
    http://www.hightman.cn/index.php?myft
    http://www.hightman.cn/bbs/viewthread.php?tid=18&extra=page%3D1&page=1
    因为以下文章 放弃
    参考http://www.blogjava.net/cap
    利用mysql中文分词插件,这个东西倒是很好,但是偏偏只支持mysql4.0,和mysql 5.1 beta, 刚好不支持我目前用的mysql5.0.x 由于没有现成版本可以用, 也只好放弃

    还发现一个 但未试验
    参考http://www.lietu.com/doc/MysqlSeg.htm

    一、来源
    Mysql全文检索的解析器缺省是按空格切分的,不能直接支持全文检索中文。从5.1版本开始,Mysql全文检索的解析器以插件的方式提供。猎兔提供符合Mysql插件格式的中文分词模块。
    二、环境与安装
    首先下载Mysql5.1版本。然后在gb2312或gbk的环境下启动Mysql服务。

    # cd /usr/local/mysql/bin
    # ./mysqld-max --user=mysql --default-character-set=gbk
    把seg.so拷贝到插件指定的路径,缺省是 /usr/local/mysql/lib/mysql
    # cp ./seg.so /usr/local/mysql/lib/mysql/seg.so
    把词典拷贝到Mysql的Data路径下的Dic子目录,缺省是 /usr/local/mysql/data/Dic/
    进入Mysql:
    # mysql --default-character-set=gbk
    安装插件:
    mysql>INSTALL PLUGIN cn_parser SONAME 'seg.so';
    三、使用中文分词插件
    创建表:
    mysql>CREATE TABLE t (c VARCHAR(255), FULLTEXT (c) WITH PARSER cn_parser) default charset gbk;
    mysql>INSERT INTO t VALUES ('测试中文');
    mysql>INSERT INTO t VALUES ('老师说明天开会');
    mysql> INSERT INTO t VALUES ('购买手机');
    查询:
    mysql> SELECT MATCH(c) AGAINST('说明'),c FROM t;

    +-----------------------------------+-----------------------+

    | MATCH(c) AGAINST('说明') | c |

    +-----------------------------------+-----------------------+

    | 0 | 测试中文 |

    | 0 | 老师说明天开会 |

    | 0 | 购买手机 |

    +-----------------------------------+-----------------------+

    3 rows in set (0.00 sec)

    mysql> SELECT MATCH(c) AGAINST('说'), c FROM t;

    +--------------------------------+-----------------------+

    | MATCH(c) AGAINST('说') | c |

    +--------------------------------+-----------------------+

    | 0 | 测试中文 |

    | 0.58370667695999 | 老师说明天开会 |

    | 0 | 购买手机 |

    +--------------------------------+-----------------------+

    3 rows in set (0.00 sec)

    相关文章

    精彩推荐