如何使用mysql的全文索引搜索

如何使用mysql的全文索引搜索,第1张

你有没有想过如何使用搜索功能在所有整站中实现!互联网博客和网站,大多数都采用MySQL数据库。MySQL提供了一个美妙的方式实施一个小的搜索引擎,在您的网站(全文检索)。所有您需要做的是拥有的MySQL 4.x及以上。MySQL提供全文检索功能,我们可以用它来 ??实现搜索功能。

首先,让我们为我们的例子中设置一个示例表。我们将创建一个名为第一个表。

CREATE TABLE articles (

id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,

title VARCHAR(200),

body TEXT,

FULLTEXT (title,body)

)

在此表中还可以添加一些示例数据。执行后,插入查询。

INSERT INTO articles (title,body) VALUES

('MySQL Tutorial','DBMS stands for DataBase ...'),

('How To Use MySQL Well','After you went through a ...'),

('Optimizing MySQL','In this tutorial we will show ...'),

('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),

('MySQL vs. YourSQL','In the following database comparison ...'),

('MySQL Security','When configured properly, MySQL ...')

一旦样本数据是准备好,我们可以开始我们的全文检索功能。

自然语言全文搜索

尝试我们的示例表上执行下面的SELECT查询。

SELECT * FROM articles

WHERE MATCH (title,body) AGAINST ('database')

你就能看到结果如下:

在下面的数据库比较5 MySQL与YourSQL的...

MySQL教程DBMS 1代表数据库...

我们在上面的SQL查询(标题,正文)反对(“数据库”)的比赛,选择所有的记录,列标题和正文进行全文搜索。

您可以修改该查询,并创建您自己的版本,以自己的数据库中执行全文搜索。

布尔全文搜索

它可能发生,你要指定某些关键字在您的搜索条件。此外,您可能要忽略某些关键字。布尔全文搜索可以用来执行这些要求的全文检索。

检查下面的SELECT查询。

SELECT * FROM articles WHERE MATCH (title,body)

AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE)

如果您发现上述选择查询,我们增加了布尔MODE反对()。这个查询将获取MySQL的关键字,但不YourSQL关键字的所有记录。请注意+和-我们以前指定的关键字!

在执行此功能,MySQL使用什么有时也被称为布尔逻辑作为暗示,其中:+代表与-代表不是[无 *** 作员]暗示或

以下是几个例子布尔搜索条件。

“苹果香蕉

查找行至少包含两个词之一。

“+苹果+果汁”

寻找包含两个单词的行。

“+苹果Macintosh

查找行包含“苹果”,但排名的行,如果它们也包含“麦金塔”。

“+苹果Macintosh的”

查找行包含“苹果”这个词,而不是“麦金塔”。

'+苹果Macintosh的“

查找包含单词“苹果”的行,但如果该行也包含单词“麦金塔”,速度比如果行不低。这是“软”比“+苹果Macintosh电脑”,为“麦金塔”的存在,导致该行不能在所有返回的搜索。

'+苹果+(>营业额<馅饼)“

行包含“苹果”和“营业额”,或“苹果”和“馅饼”(任何顺序)的话,但排名“苹果的营业额”比“苹果馅饼“。

限制

支持全文检索的MyISAM表只。MySQL 4.1中,使用多个字符设置一个单一的表内的支持。然而,在一个FULLTEXT索引的所有列,必须使用相同的字符集和校对规则。MATCH()列列表必须匹配完全在一些列清单表的FULLTEXT索引定义,除非这场比赛()是在布尔模式。布尔模式搜索,可以做非索引列,虽然他们很可能是缓慢的。

自己在写一个web,希望对数据库做全文检索。但是google了解到,由于中文分词的缘故,mysql只支持英文的全文搜索,想支持中文的,需要各种插件or实现一些比较复杂的机制,而买的虚拟主机并不支持这些复杂的东西。仔细想了下,因为自己需求的功能也比较简单,主要是2个字段的搜索,且数据量不大,即便增加几个字段,需要多运行几个select也不会对速度有太大影响,所以通过一些work around实现了需求。Step 1:用locate进行简单的搜索Locate可以判断子串是否在子乱 有两个column,一个name,一个description.所以可以用LOCATE>0去判断是否关键字在其中出现了。 其实就是 SELECT * FROM table WHERE LOCATE(key, 'name')>0 OR LOCATE(key, 'description)这样,我们就简单实现了对某个key在两个域的搜索Step 2:搜索多个关键字 通常,搜索都是有多个关键字,所以我们需要对每个关键字,执行下Step1的查询。(当然,也可以合成一个,这里偷懒每次只查询1个关键字) 然后,我们再将每次查询出的数组都合并,这样就得到了一个最终的集合。php代码如下:

function selectlocate($tarcols,$skey){ 

    $where =""

    $connector = " "

    global $count

    foreach($tarcols as $tarcol ){

        $where .= $connector

        $where .= "LOCATE('$skey', $tarcol) != 0  "

        if($connector == " "){

            $connector = " OR "

        }

    }

    $sql = "SELECT * FROM pets_table WHERE $where"

    $result = mysql_query($sql)

    $ret = Array()

    while($item = mysql_fetch_array($result, MYSQL_ASSOC)){

        $count ++

        $ret[] = $item

    }

    return $ret

}

Step 3:匹配的权重 上面Step2的结果,其实是无序的。通常,如果我们搜索一个字段:1.如果这个字段和关键字完全相同,那么一般来讲,可能这个结果应该是相关度最高的2.如果他只是其其中出现了一次,相关度就最低。3.如果他出现的次数比在其他row中出现的次数高,那么他的相关度就比2中的结果高 所以,搜索的时候依据这个顺序考虑权重,a.如果完全相等,权重为1000 b.如果出现1次,权重为10,出现n次c.权重为n*10每次搜索出来的结果附加上权重----》然后合并相同项----》并把权重累加 最后按权重排序,即可得到一个有排序的搜索结果。 以下是两种1关键字对应1个字段(上面的代码是1关键字多个字段)查询的代码(不包含合并两个数组的代码,相关的代码在Step4中),只需遍历每个关键字和字段,就能完成搜索

$count = 0 

function selectequal($col,$skey){

    $connector = " "

    global $count

    $sql = "SELECT * FROM pets_table WHERE LOWER($col)=LOWER('$skey')"

    $result = mysql_query($sql)

    $ret = Array()

    while($item = mysql_fetch_array($result, MYSQL_ASSOC)){

        $count ++

        $item["weight"] = 1000

        $ret[] = $item

    }

    return $ret

}

function selectlocate($col,$skey){

    global $count

    $sql = "SELECT *,(LENGTH(description) - LENGTH(REPLACE(description, '$skey', '')))/LENGTH('$skey') *10 as weight FROM pets_table WHERE LOCATE(LOWER('$skey'),LOWER($col))>0"

    $result = mysql_query($sql)

    $ret = Array()

    while($item = mysql_fetch_array($result, MYSQL_ASSOC)){

        $count ++

        $ret[] = $item

    }

    return $ret

}

 Step 4: 字段的权重 在我的需求中,显然name这个字段比description更重要,所以在匹配时,对name字段的结果应该有所倾斜,所以,又可以增加一个对字段的权重系数。1.如果是在name域的匹配,设系数为10;2.如果是在description匹配,设系数为1; 将Step 3每次计算得出的权重,再乘上这个系数,就可以得到一个新的,更有效的权重值。 最后按权重排序,即可得到一个最有相关度排序的搜索结果 其他的细节: 如果一个关键字已经满足了equal条件,那么再使用locate条件的时候会依然返回一个结果,所以在使用locate条件的时候,过滤掉equal的情况

点击(此处)折叠或打开

<?php 

$count = 0

function selectequal($col,$val,$skey){

    $connector = " "

    global $count

    $sql = "SELECT * FROM pets_table WHERE LOWER($col)=LOWER('$skey')"

    $result = mysql_query($sql)

    $ret = Array()

    while($item = mysql_fetch_array($result, MYSQL_ASSOC)){

        $count ++

        $item["weight"] = 1000*$val

        $ret[] = $item

    }

    return $ret

}

function selectlocate($col,$val,$skey){

    global $count

    $sql = "SELECT *,(LENGTH(description) - LENGTH(REPLACE(description, '$skey', '')))/LENGTH('$skey') *10*$val as weight FROM pets_table WHERE LOCATE(LOWER('$skey'),LOWER($col))>0 AND LOWER($col)!=LOWER('$skey')"

    $result = mysql_query($sql)

    $ret = Array()

    while($item = mysql_fetch_array($result, MYSQL_ASSOC)){

        $count ++

        $ret[] = $item

    }

    return $ret

}

function cleanarr($arr){

    global $count

    $tmp = Array()

    $tmpall = Array()

    foreach($arr as $item){

        if(array_key_exists($item['uid'], $tmp)){

            $tmp[$item['uid']]+=$item["weight"]

        }

        else{

            $tmp[$item['uid']] = $item["weight"]

            $tmpall[$item['uid']] = $item

        }

    }

    //sort by weight in descending order 

    arsort($tmp)

    $ret = Array()

    //rebuild the return arary 

    $count = 0

    foreach($tmp as $k=>$v){

        $count++

        $tmpall[$k]['weight']=$v

        $ret[]=$tmpall[$k]

    }

    return $ret

}

require_once("consvr.php")

    $colshash = array("name"=>10,"description"=>1)

    $ret = Array()

    $keywords=explode(" ", $keywords)

    $cols = array_keys($colshash)

    foreach($keywords as $keyword){

        foreach($colshash as $col=>$val){

            $ret = array_merge($ret,selectequal($col,$val, $keyword))

            $ret = array_merge($ret,selectlocate($col,$val, $keyword))

        }

        

    }

    $ret = cleanarr($ret)

    $ret = array('msg' => "Success", 'count'=>$count,'children' => $ret, 'query'=>"COMPLEX:NOT READABLE")

    echo json_encode($ret)

    mysql_close()

?>


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/7196431.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-02
下一篇 2023-04-02

发表评论

登录后才能评论

评论列表(0条)

保存