建立全文索引(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(); } }
啦啦啦