中文分詞+數(shù)據(jù)庫分表

1. 要求

  1. 對文章內(nèi)容進(jìn)行關(guān)鍵詞檢索独柑,找到符合的關(guān)鍵詞的文章
  2. 對數(shù)據(jù)庫表優(yōu)化(針對大型項(xiàng)目)喇勋,進(jìn)行分表讀寫數(shù)據(jù)(本次創(chuàng)建32個表)

2. 思路

  1. 創(chuàng)建32張數(shù)據(jù)表(art0-31)罗珍,包含字段(art_id,guid秀鞭,cat_id,title,content,pubtime),根據(jù)需要自己可以添加
  2. 創(chuàng)建索引表(index_art)榕茧,包含字段(guid,id诽偷,content)這塊可以把數(shù)據(jù)表名稱也加上坤学,好定位到那張表,根據(jù)需要可以添加报慕,這里要把content創(chuàng)建全文索引
  3. 這里如何讓索引表和數(shù)據(jù)表進(jìn)行關(guān)聯(lián)深浮,因?yàn)槊總€數(shù)據(jù)表都有自增長art_id,都是從1開始眠冈,無法和索引表進(jìn)行關(guān)聯(lián)飞苇,所以需要引入uuid,即每個文章都有一個自己uuid,索引表也對應(yīng)文章的uuid
  4. 創(chuàng)建了32張數(shù)據(jù)表布卡,那么如何實(shí)現(xiàn)減輕數(shù)據(jù)庫壓力呢雨让,怎么把數(shù)據(jù)隨機(jī)插入到表中,這里使用了對uuid的處理羽利,即先對uuid進(jìn)行md5加密處理轉(zhuǎn)行成16進(jìn)制宫患,然后利用substr提取前兩位字符,再用hexdec函數(shù)將其轉(zhuǎn)換成10機(jī)制这弧,讓最后結(jié)果和32取余數(shù)娃闲,余數(shù)和art拼接就是插入的表名
  5. 當(dāng)插入數(shù)據(jù)時,還要同時插入到索引表中(最好用數(shù)據(jù)庫事務(wù)處理)匾浪,因?yàn)槲恼聝?nèi)容可能是中文皇帮,英文或者混合,這里需要判斷下蛋辈,如果是含有中文就需要對中文進(jìn)行處理属拾,通過中文分詞字典,分出詞語冷溶,并用空格分開渐白,英文的話直接插入(自帶空格)
  6. 當(dāng)讀取修改刪除數(shù)據(jù)時,都要用到uuid逞频,所以就不能用自增長id了(跳轉(zhuǎn)頁面時的參數(shù))纯衍。
  7. 當(dāng)提交檢索時,也要對語句進(jìn)行判斷處理苗胀,然后用全文索引語句襟诸,在index_art索引表中搜索,存在數(shù)據(jù)基协,取得uuid歌亲,然后利用uuid找到對應(yīng)的表,取得數(shù)據(jù)

代碼

  1. 數(shù)據(jù)表結(jié)構(gòu):
1 (4).png
3.png
//artadd.php
//獲取guid
    $uuid4 = Uuid::uuid4(); 
    $index['guid']=$art['guid']=$uuid4->toString();
    //獲取uuid澜驮,md5加密之后再獲取前兩位數(shù)字陷揪,最后轉(zhuǎn)換成10進(jìn)制,
    $num=hexdec(substr(md5($uuid4->toString()),0,2));
    $yu=$num%32;
    $table='art'.$yu;
    ~
    ~
    //當(dāng)插入成功后杂穷,在索引表中添加數(shù)據(jù)
        //檢查內(nèi)容是什么類型(1->英文鹅龄,2->中文)
        $cont=isWhat($art['content']);//自己封裝的函數(shù)
        if($cont==1){
            $index['content']=$art['content'];
        }elseif($cont==2){
            //利用fenci中文字典更改內(nèi)容
            //實(shí)例化字典
            $se=new segment();
            //調(diào)用方法
            $index['content'] = $se->get_keyword($art['content']);      
        }else{
            //利用fenci中文字典更改內(nèi)容
            //實(shí)例化字典
            $se=new segment();
            //調(diào)用方法
            $index['content'] = $se->get_keyword($art['content']);
            $words=split_en_str($art['content'],false);
            $index['content'].=" ".implode(' ',$words);
        }
        //插入index_art索引表中
        inUp('index_art',$index,'insert');//自己封裝的插入函數(shù)
  1. 修改數(shù)據(jù)(刪除比較簡單就不寫了)
//artedit.php

//獲取到需要改的數(shù)據(jù)
    $num=hexdec(substr(md5($_GET['id']),0,2));
    $yu=$num%32;
    $table='art'.$yu;
    $sql="select guid,title,tags,content,cat_id from ".$table." where guid='".$_GET['id']."'";
    $art=find($sql);
    ~
    ~
//當(dāng)有post提交時
    $num=hexdec(substr(md5($_POST['guid']),0,2));
    $yu=$num%32;
    $table='art'.$yu;
    //更新成功后把索引文件中的content字段進(jìn)行更新
    //檢查內(nèi)容是什么類型(1->英文,2->中文)
    $cont=isWhat($art['content']);
    if($cont==1){
        $index['content']=$art['content'];
    }elseif($cont==2){
        //利用fenci中文字典更改內(nèi)容
        //實(shí)例化字典
        $se=new segment();
        //調(diào)用方法
        $index['content'] = $se->get_keyword($art['content']);      
    }else{
        //利用fenci中文字典更改內(nèi)容
        //實(shí)例化字典
        $se=new segment();
        //調(diào)用方法
        $index['content'] = $se->get_keyword($art['content']);
        $words=split_en_str($art['content'],false);
        $index['content'].=" ".implode(' ',$words);
    }
    //插入index_art索引表中
    inUp('index_art',$index,'update',"guid='".$_POST['guid']."'");

查數(shù)據(jù)

//artlist.php
//分頁操作
$num='';
for($i=0;$i<32;$i++){
    $sql="select count(*) from art".$i;
    $num+=find($sql)['count(*)'];
}

$cnt=10;
$curr=isset($_GET['page'])? $_GET['page'] : '1';
//調(diào)用分頁函數(shù)亭畜,進(jìn)行分頁
$page=getPage($num,$cnt,$curr);//自己封裝的函數(shù)
//獲取art表的所有文章
$rs=[];
for($i=0;$i<32;$i++){
    $sql="select title,guid,art_id,pubtime,catname from art".$i." left join cat on cat.cat_id=art".$i.".cat_id";
    //echo $sql.'<br>';
    $a=getAll($sql);
    foreach($a as $v){
        $rs[]=$v;
    }
}
$rs=array_slice($rs,($curr-1)*$cnt,$cnt);//html頁面去遍歷$rs
~
~
//artlist.html
//遍歷文章
<?php foreach($rs as $k=>$v){?>
    <tr>
        <td><?php echo ($k+1);?></td>
        <td><?php echo date('Y-m-d',$v['pubtime'])?></td>
        <td><a href="#"><?php echo $v['title']?></a></td>
        <td><?php echo $v['catname']?></td>
  
         <td>
            <a href="./artdel.php?id=<?php echo $v['guid']?>">刪除</a>|
            <a href="./artedit.php?id=<?php echo $v['guid']?>">修改</a>
        </td>
    </tr>
<?php } ?>

//分頁
<?php if(isset($page)){ ?>
    <div id="pagebar" align='center' style='font-size:20px'>
        共<?php echo $num;?>條 
        <?php foreach($page as $k=>$v){
            if($k==$curr){
        ?>              
        <span>[<?php echo $k;?>]</span>
        <?php }else{?>
            <a href='artlist.php?<?php echo $v; ?>'><?php echo $k; ?></a>
        <?php }
        }
        ?>
    </div>
<?php }?>

當(dāng)提交查詢時

//index.php
//檢查內(nèi)容是什么類型(1->英文扮休,2->中文)
    $cont=isWhat($_POST['search']);//自己封裝函數(shù)
    if($cont==1){
        $search=$_POST['search'];
    }elseif($cont==2){
        //利用fenci中文字典更改內(nèi)容
        //實(shí)例化字典
        $se=new segment();
        //調(diào)用方法
        $search = $se->get_keyword($_POST['search']);   
    }else{
        //利用fenci中文字典更改內(nèi)容
        //實(shí)例化字典
        $se=new segment();
        //調(diào)用方法
        $search = $se->get_keyword($_POST['search']);
        $words=split_en_str($_POST['search'],false);
        $search.=" ".implode(' ',$words);
    }
    //利用全文索引的語句查詢
    $sql="select guid from index_art where MATCH(content) AGAINST('".$search."' IN BOOLEAN MODE)";
    $rs=getAll($sql);
    $art=[];
    if(!empty($rs)){
        foreach($rs as $v){
        $num=hexdec(substr(md5($v['guid']),0,2));
        $yu=$num%32;
        $table='art'.$yu;
        $sql="select guid,pubtime,title,content,catname from ".$table." inner join cat on $table.cat_id=cat.cat_id  where guid='".$v['guid']."'";
        //獲取到當(dāng)前guid的值
        $one=find($sql);
        //將關(guān)鍵字分割為數(shù)組
        $key_word=explode(' ',$search);
        //獲取關(guān)鍵詞出現(xiàn)的次數(shù)
        $sql="select content from index_art where guid='".$v['guid']."'";
        //var_dump(find($sql));die;
        $content=find($sql)['content'];
        $n='';
        foreach($key_word as $v1){
            $n+=substr_count($content,$v1);
            //將數(shù)據(jù)中的關(guān)鍵詞高亮顯示
            $one['content']=preg_replace("/($v1)/i","<font color=red><b>\\1</b></font>",$one['content']);
        }
        $one['num']=$n;
        //將num插入到$one中
        $art[]=$one;
        //利用冒泡法根據(jù)num排序
        bubble_sort($art);
            
    }
        //頁面去遍歷$art
    }

使用到封裝的函數(shù)

/**
*
*分頁函數(shù)
*當(dāng)$max>=5默認(rèn)顯示5個條頁碼,<5正常顯示
*@param int $num文章數(shù)
*@param int $cnt每頁顯示條數(shù)
*@param int $curr當(dāng)前頁
*@return array 返回拼接的每頁的url參數(shù) 
*/
function getPage($num,$cnt,$curr){
    //獲取最大頁碼
    $max=ceil($num/$cnt);
    //判斷顯示頁碼的最左邊的位置
    $left=max($curr-2,1);
    //最右邊頁碼
    $right=min($left+4,$max);
    //存在一種情況是拴鸵,當(dāng)共9頁玷坠,當(dāng)前處于8頁蜗搔,頁面只會顯示4個分頁,所以需要根據(jù)$right重新定義下left
    $left=max($right-4,1);
    //將獲取到的頁碼放到數(shù)組中返回八堡,因?yàn)閷τ趇ndex頁面樟凄,存在兩個查詢,一個時根據(jù)欄目查詢(有參數(shù)cat_id)兄渺,一個查詢吃總的欄目缝龄,所以需要用http_build_query()函數(shù)來保留原有的參數(shù)
    for($i=$left;$i<=$right;$i++){
        $_GET['page']=$i;//模擬url輸出格式是?page=$i,與原有的參數(shù)拼接
        $page[$i]=http_build_query($_GET);
    }
    return $page;
}

/**
*
*判斷字符串時全英文挂谍,全中文叔壤,或者都有
*@param string $str1 需要檢查的字符串
*@return int 英文->1 中文->2 混合->3
*/
function isWhat($str1){
    $strA= trim($str1);    
    $lenA= strlen($strA); //檢測字符串實(shí)際長度
    $lenB= mb_strlen($strA, "utf-8"); //文件的編碼方式要是UTF8     
    if($lenA=== $lenB) {    
        return"1";//全英文    
    }else {    
       if($lenA% $lenB== 0) {    
           return"2";//全中文    
       }else {    
           return"3";//中英混合    
       }    
   }
}
/**
*
*匹配英文單詞
*@param string $str 需要匹配的字符
*@param bool $distinct 是否去除重復(fù)值
*@return array 返回所有單詞的索引數(shù)組
*/
function split_en_str($str,$distinct=true) {
    preg_match_all('/([a-zA-Z]+)/',$str,$match);
    if ($distinct == true) {
    $match[1] = array_unique($match[1]);
    }
    sort($match[1]);
    return $match[1];
}
/**
*
*冒泡法排序
*
*
*/
function bubble_sort(& $arr){
    $number=count($arr);
    for($i=0;$i<$number-1;$i++){
      for($j=0;$j<$number-1-$i;$j++){
       if($arr[$j]['num']<$arr[$j+1]['num']){
        $tmp=$arr[$j];
        $arr[$j]=$arr[$j+1];
        $arr[$j+1]=$tmp;
        
        }
      
       } 
    return $arr;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市口叙,隨后出現(xiàn)的幾起案子炼绘,更是在濱河造成了極大的恐慌,老刑警劉巖妄田,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俺亮,死亡現(xiàn)場離奇詭異,居然都是意外死亡疟呐,警方通過查閱死者的電腦和手機(jī)脚曾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來启具,“玉大人本讥,你說我怎么就攤上這事「恢剑” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵旨椒,是天一觀的道長晓褪。 經(jīng)常有香客問我,道長综慎,這世上最難降的妖魔是什么涣仿? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮示惊,結(jié)果婚禮上好港,老公的妹妹穿的比我還像新娘。我一直安慰自己米罚,他們只是感情好钧汹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著录择,像睡著了一般拔莱。 火紅的嫁衣襯著肌膚如雪碗降。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天塘秦,我揣著相機(jī)與錄音讼渊,去河邊找鬼。 笑死尊剔,一個胖子當(dāng)著我的面吹牛爪幻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播须误,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼挨稿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了霹期?” 一聲冷哼從身側(cè)響起叶组,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎历造,沒想到半個月后甩十,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吭产,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年侣监,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臣淤。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡橄霉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邑蒋,到底是詐尸還是另有隱情姓蜂,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布医吊,位于F島的核電站钱慢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏卿堂。R本人自食惡果不足惜束莫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望草描。 院中可真熱鬧览绿,春花似錦、人聲如沸穗慕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逛绵。三九已至诀蓉,卻和暖如春栗竖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背渠啤。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工狐肢, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沥曹。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓份名,卻偏偏與公主長得像,于是被迫代替她去往敵國和親妓美。 傳聞我的和親對象是個殘疾皇子僵腺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容