MySQL 全文檢索 ngram Mybatis

建立全文索引(FullText index)html

  建立表的同時建立全文索引前端

    FULLTEXT (name) WITH PARSER ngramjava

  經過 alter table 的方式來添加sql

    alter table `das`.`staff_base` add fulltext index staff_base_name(`name`) with parser ngram;數據庫

  直接經過create index的方式(未測試)apache

    CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`)oracle

    也能夠在建立索引的時候指定索引的長度:app

    CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`(20))ide

刪除全文索引(未測試)post

  直接使用 drop index(注意:沒有 drop fulltext index 這種用法)

    DROP INDEX full_idx_name ON tommy.girl ;

  使用 alter table的方式

    ALTER TABLE tommy.girl DROP INDEX ft_email_abcd;

使用全文索引

  使用全文索引的格式:  MATCH (columnName) AGAINST ('string')

1. 天然語言模式下檢索:

  獲得符合條件的個數

SELECT COUNT(*) FROM articles WHERE MATCH (title,body) AGAINST ('數據庫' IN NATURALLANGUAGE MODE);

  獲得匹配的比率

SELECT id, MATCH (title,body) AGAINST ('數據庫' IN NATURAL LANGUAGE MODE) AS score FROM articles;

2. 布爾模式下搜索,這個就相對於天然模式搜索來的複雜些:

  匹配既有管理又有數據庫的記錄

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+數據庫 +管理' IN BOOLEAN MODE);

  匹配有數據庫,可是沒有管理的記錄

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+數據庫 -管理' IN BOOLEAN MODE);

  匹配MySQL,可是把數據庫的相關性下降

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('>數據庫 +MySQL' INBOOLEAN MODE);

3. 查詢擴展模式,好比要搜索數據庫,那麼MySQL,oracle,DB2也都將會被搜索到

SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('數據庫' WITH QUERY EXPANSION);

4. ft_boolean_syntax (+ -><()~*:""&|)使用的例子:

  + : 用在詞的前面,表示必定要包含該詞,而且必須在開始位置。

    eg: +Apple 匹配:"Apple123" , "tommy, Apple"

  - : 不包含該詞,因此不能只用「-yoursql」這樣是查不到任何row的,必須搭配其餘語法使用。

    eg: MATCH (name) AGAINST ('-lime +oracle') 

    匹配到: 全部不包含lime,但包含oracle的記錄 

  空(也就是默認狀況),表示可選的,包含該詞的順序較高。 

     例子:

      apple banana    找至少包含上面詞中的一個的記錄行。或的關係

      +apple +juice    兩個詞均在被包含。與的關係

      +apple macintosh    包含詞 「apple」,可是若是同時包含 「macintosh」,它的排列將更高一些

      +apple -macintosh    包含 「apple」 但不包含 「macintosh」

  > :提升該字的相關性,查詢的結果會排在比較靠前的位置。 

  < :下降相關性,查詢的結果會排在比較靠後的位置。

     先不使用 >< 能夠看到徹底匹配的排的比較靠前

select * from tommy.girl where match(girl_name) against('張欣婷' in boolean mode);

    單獨使用 > 使用了>的李秀琴立刻就排到最前面了

select * from tommy.girl where match(girl_name) against('張欣婷 >李秀琴' in boolean mode);

    單獨使用 < 看到沒,不是人也排到最前面了,這裏使用的但是 < 哦,說好的下降相關性呢,往下看吧。

select * from tommy.girl where match(girl_name) against('張欣婷 <不是人' in boolean mode);

    同時使用>< 到這裏終於有答案了,只要使用了 ><的都會往前排,並且>的老是排在<的前面

    1. 只要使用 ><的總比沒用的 靠前

    2. 使用  >的必定比 <的排的靠前 (這就符合相關性提升和下降)

    3. 使用同一類的,使用的越早,排的越前。

 select * from tommy.girl where match(girl_name) against('張欣婷 >李秀琴 <練習冊 <不是人>是個鬼' in boolean mode);

  ( ):能夠經過括號來使用字條件。  

    eg: +aaa +(>bbb <ccc)  

    找到有aaa和bbb和ccc,aaa和bbb,或者aaa和ccc(由於bbb,ccc前面沒有+,因此表示無關緊要),而後 aaa&bbb > aaa&bbb&ccc > aaa&ccc

  ~ :將其相關性由正轉負,表示擁有該字會下降相關性,但不像「-」將之排除,只是排在較後面。 

    eg:   +apple ~macintosh   先匹配apple,但若是同時包含macintosh,就排名會靠後。

  * :通配符,這個只能接在字符串後面。 

    MATCH (girl_name) AGAINST ('+*ABC*')   #錯誤,不能放前面

    MATCH (girl_name) AGAINST ('+張筱雨*')  #正確

  " " :總體匹配,用雙引號將一段句子包起來表示要徹底相符,不可拆字。

    eg:  "tommy huang" 能夠匹配  tommy huang xxxxx   可是不能匹配  tommy is huang。

 MyBatis 中 使用 全文索引注意:

  前端傳入數據格式name:"",name:"lime oracle"

package com.das.mapper.service;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.SQL;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author liangmy
 * @Date 2018/2/26
 */
public class ServiceBaseProvider {

    public String getServiceBaseList(Map<String, Object> map){
        StringBuffer name = new StringBuffer();
        for(String str : (null == map.get("name") ? " " : map.get("name").toString().trim() + " ").split(" ")){
            name.append("+" + str + " ");
        }
        if(name.length() > 2) {
            name.deleteCharAt(name.length() - 1);
        }
        String level = null == map.get("level") ? "" : map.get("level").toString();
        return new SQL(){
            {
                SELECT("id");
                FROM("service_base");
                if(!StringUtils.isEmpty(name)) {
                    WHERE("MATCH(name) AGAINST('" + name.toString() + "' IN BOOLEAN MODE)");
                }
                if(!StringUtils.isEmpty(level)){
                    AND().WHERE("JSON_CONTAINS(level,'" + level + "')");
                }
            }
        }.toString();
    }
}

   前端傳入數據格式name:"",name:"lime 1026", name:"1026" :  mobile:"",mobile:"lime 1026", mobile:"1026"

package com.das.mapper.staff;

import com.das.common.type.StaffBaseStatusEnum;
import com.das.common.type.StaffRecordTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.SQL;

import java.util.Map;

/**
 * @Author liangmy
 * @Date 2018/2/9
 */
public class StaffProvider {

    public String getIdList(Map<String, Object> map){
        Long storeBaseId = (Long) map.get("storeBaseId");
        Long postBaseId = (Long) map.get("postBaseId");
        StaffBaseStatusEnum status = (StaffBaseStatusEnum) map.get("status");
        String name = (String) map.get("name");
        String mobile = null == map.get("mobile") ? "" : "\"" + map.get("mobile") + "\"";
        return new SQL(){
            {
                SELECT("`staff_base`.`id`");
                FROM(" `das`.`staff_base`");
                if(null != storeBaseId && storeBaseId > 0){
                    WHERE("store_base_id = #{storeBaseId}");
                }
                if(null != postBaseId && postBaseId > 0){
                    AND().WHERE("post_base_id = #{postBaseId}");
                }
                if(null != status){
                    AND().WHERE("status = #{status}");
                }
                if(StringUtils.isNotEmpty(name)){
                    AND().WHERE("MATCH(name) AGAINST('" + name + "' IN BOOLEAN MODE)");
                }
                if(StringUtils.isNotEmpty(mobile)){
                    AND().WHERE("MATCH(mobile) AGAINST('" + mobile + "' IN BOOLEAN MODE)");
                }
            }
        }.toString();
    }
}

   前端傳入數據格式carNum:"",carNum:"1026"

package com.das.mapper.order;

import com.das.common.type.ReceiveBaseDurationEnum;
import com.das.common.type.VipTypeEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.SQL;

import java.util.Map;


/**
 * @Author liangmy
 * @Date 2018/2/28
 */
public class ReceiveBaseProvider {

    public String getReceiveBaseIdList(Map<String, Object> map) {
        ReceiveBaseDurationEnum duration = (ReceiveBaseDurationEnum) map.get("duration");
        VipTypeEnum type = (VipTypeEnum) map.get("type");
        String carNum = null == map.get("carNum") ? "" : "\"" + map.get("carNum") + "\"";
        return new SQL() {
            {
                SELECT("id");
                FROM("receive_base");
                if (null != duration) {
                    switch (duration){
                        case TODAY:
                            WHERE("TO_DAYS(mgt_create) = TO_DAYS(NOW())");
                            break;
                        case WEEK:
                            WHERE("DATE_SUB(CURDATE(), INTERVAL 7 DAY) <= date(mgt_create)");
                            break;
                        case MONTH:
                            WHERE("DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(mgt_create)");
                            break;
                        case QUARTER:
                            WHERE("DATE_SUB(CURDATE(), INTERVAL 60 DAY) <= date(mgt_create)");
                            break;
                    }
                }
                if (null != type){
                    AND().WHERE("JSON_CONTAINS(vip_base_type_item,'" + type + "')");
                }
                if(!StringUtils.isEmpty(carNum)){
                    AND().WHERE("MATCH(car_num) AGAINST('" + carNum + "' in boolean mode)");
                }
                ORDER_BY("mgt_create");
            }
        }.toString();
    }
}

 

 

啦啦啦

MySQL使用全文索引(fulltext index)

InnoDB全文索引:N-gram Parser【轉】

相關文章
相關標籤/搜索