【转载保存】lucene正则查询使用注意
今天要分享的是關于lucene中另外一種豐富的查詢方式----正則查詢,lucene內置了許多的查詢API,以及更強大的自定義查詢方式的QueryParse,大部分情況下我們使用內置的查詢API,基本上就可以滿足我們的需求了,但是如果你想更靈活的定制自己的查詢或者改寫自己的查詢API那么你完全可以繼承QueryParse類來完成這項工作。?
從某種方式上來說,正則查詢(RegexpQuery)跟通配符查詢(WildcardQuery)的功能很相似,因為他們都可以完成一樣的工作,但是不同的是正則查詢支持更靈活定制細化查詢,這一點與通配符的泛化是不一樣的,而且正則查詢天生支持使用強大的正則表達式的來準確匹配一個或幾個term,需要注意的是,使用正則查詢的字段最好是不分詞的,因為分詞的字段可能會導致邊界問題,從而使查詢失敗,得不到任何結果,這一點和WildcardQuery效果是一樣的。?
下面先來看一下,散仙的測試數據,為了看出分詞與不分詞給查詢造成的影響,散仙的用同樣的內容做測試,分詞工具使用的是IK的分詞器,截圖如下:?
在上圖中,散仙使用2個字段存儲一樣的內容,一個是分過詞的,一個沒分過詞的,下面給出使用正則查詢的核心代碼:
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","量并");結果如下:
命中數據?: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查詢,當然使用正則表達式查詢方式可以有很多種,在這里只是簡單的舉了個例子,有興趣的朋友們,可以自己測測。?
最后在總結一下,1,如果是在不分詞的字段里做模糊檢索,優先使用正則查詢的方式會比其他的模糊方式性能要快。2,在查詢的時候,應該注意分詞字段的邊界問題。3,在使用OR或AND拼接條件查詢時或一些特別復雜的匹配時,也應優先使用正則查詢。4,大數據檢索時,性能尤為重要,注意應避免使用前置模糊的方式,無論是正則查詢還是通配符查詢。?
總結
以上是生活随笔為你收集整理的【转载保存】lucene正则查询使用注意的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么可以通过类名调用静态方法?
- 下一篇: IO之数据流