本篇是關於lucene中另一種豐富的查詢方式---正則查詢,lucene內置了許多的查詢api,以及更強大的自定義查詢方式的QueryParse,大部分狀況下咱們使用內置的查詢api,基本上就能知足咱們的需求了,可是若是想要靈活的定製本身的查詢或者改寫本身的查詢api,那麼你徹底能夠繼承QueryParse類來完成這項工做。
java
從某種方式上來講,正則查詢(RegexpQuery)跟通配符查詢(WildcardQuery)的功能很類似,由於他們均可以完成同樣的工做,可是不一樣的是正則查詢支持更靈活定製細化查詢,這一點與通配符的泛化是不同的,並且正則查詢天生支持使用強大的正則表達式的來準確匹配一個或幾個term,須要注意的是,使用正則查詢的字段最好是不分詞的,由於分詞的字段可能會致使邊界問題,從而使查詢失敗,使得不到任何結果,這一點和WildcardQuery效果是同樣的。
正則表達式
下面先來看一下,散仙的測試數據,爲了看出分詞與不分詞給查詢形成的影響,使用一樣的內容作測試,分詞工具使用的是IK的分詞器,截圖以下:
sql
在上圖中,使用2個字段存儲同樣的內容,一個是分過詞的,一個沒分過詞的,下面使用正則查詢的核心代碼:api
RegexpQuery query=new RegexpQuery(new Term(field, ".*"+searchStr+".*")); // System.out.println(query.toString()); TopDocs s=search.search(query,null, 100); // TopDocs s=search.search(bool,null, 100); System.out.println(s.totalHits); for(ScoreDoc ss:s.scoreDocs){ Document docs=search.doc(ss.doc); System.out.println("id=>"+docs.get("id")+" name==>"+docs.get("bookName")+" author==>"+docs.get("author")); // System.out.println(docs.get(field)); }
下面先來測,對不分詞的字段的模糊查詢,測試代碼以下:併發
dao.testRegQuery("bookName","併發");
結果以下:
工具
命中數據 :2 id=>2 name==>併發數據挑戰面臨巨大的挑戰 author==>併發數據挑戰面臨巨大的挑戰 id=>4 name==>咱們的併發數量並秦東亮在不不是很大 author==>咱們的併發數量並秦東亮在不不是很大
咱們發現它很出色的完成了模糊查詢,而且費時比通配符查詢一樣的查詢條件的費時要少,下面咱們隊分詞的字段進行檢索,測試代碼以下:性能
dao.testRegQuery("author","併發");
結果以下測試
命中數據 :3 id=>2 name==>併發數據挑戰面臨巨大的挑戰 author==>併發數據挑戰面臨巨大的挑戰 id=>3 name==>the food is perfect! author==>咱們的併發數量並非很大 id=>4 name==>咱們的併發數量並秦東亮在不不是很大 author==>咱們的併發數量並秦東亮在不不是很大
咱們對分詞字段的模糊匹配,也一樣沒問題,下面來測下對分詞字段的邊界查詢,代碼以下大數據
dao.testRegQuery("bookName","e q"); dao.testRegQuery("bookName","量並"); System.out.println("===========對比界限============="); dao.testRegQuery("author","e q"); dao.testRegQuery("author","量並");
結果以下:ui
命中數據 :1 id=>1 name==>the quick brown fox jumps over the lazy dog author==>the quick brown fox jumps over the lazy dog 命中數據 :1 id=>4 name==>咱們的併發數量並秦東亮在不不是很大 author==>咱們的併發數量並秦東亮在不不是很大 ===========對比界限============= 命中數據 :0 命中數據 :0
由以上的結果,咱們能夠發現分詞後的字段,若是在某個字之間被切分紅兩個term,那麼不管你用什麼樣的方式模糊這兩個term邊界之間的數據,都查詢不到任何結果,而部分次的字段,卻能查出來,這是由於,不分詞的字段都是做爲一個單獨的term來處理的,來lucene的內部匹配方式,偏偏又是以term做爲最小檢索單位的,故能檢索到結果,這一點須要咱們格外注意,在實現咱們的業務時,要根據本身的場景來設計出最優的分詞策略。
下面是正則表達式進行查詢,代碼以下:
dao.testRegQuery("bookName","[fb]ox");//利用正則式檢索
結果以下:
命中數據 :2 id=>1 name==>the quick brown fox jumps over the lazy dog author==>the quick brown fox jumps over the lazy dog id=>5 name==>log is small box author==>log is small box
咱們發現含有fox、box的兩條數據都被正確的檢索出來了,其實上面的檢索條件,在匹配時會被分解成4個條件,分別是,fox、fo、box、bo只要含有這幾個term的數據,都會被檢索出來,而這一點偏偏省去了,咱們在使用其餘查詢時使用OR或者AND進行拼接的繁瑣,也能夠簡化成所謂的sql裏面的IN查詢,固然使用正則表達式查詢方式能夠有不少種,在這裏只是簡單的舉了個例子。
最後總結一下:
一、若是是在不分詞的字段裏作模糊搜索,優先使用正則查詢的方式會比其餘的模糊查詢方式性能要快;
二、在查詢的時候,應該注意分詞字段的邊界問題;
三、在使用OR或AND拼接條件查詢時或一些特別複雜的匹配是,也應該優先使用正則查詢;
四、大數據檢索時,性能尤其重要,注意應該避免使用前置模糊的方式,不管是正則查詢仍是通配符查詢。