官术网_书友最值得收藏!

3.3.4 模糊匹配

關于字符串的前綴匹配問題:只查詢產品名字為字母A打頭的搜索,可以使用前綴匹配(PrefixQuery)實現。查詢語法是A*。注意,查詢的不一定是整個字段以A開頭的記錄,而只是其中的單詞以A開頭。

        Query query = new WildcardQuery(new Term(FIELD, "cut*")); // 通配符

等價于:

        Query query = new PrefixQuery(new Term(FIELD, "cut")); // 自動在結尾添加 *

測試WildcardQuery():

        // 索引一些文檔
        writer.addDocument(createDocument("1", "foo bar baz"));
        writer.addDocument(createDocument("2", "red green blue"));
        writer.addDocument(createDocument("3",
                "The Lucene was made by Doug Cutting"));
        writer.close();


        IndexReader reader = DirectoryReader.open(directory);


        IndexSearcher searcher = new IndexSearcher(reader);


        Query query = new WildcardQuery(new Term(FIELD, "cut*"));


        TopDocs topDocs = searcher.search(query, 10);

這里的cut只能是小寫,否則就匹配不上。如果用戶輸入的是大寫,如Cut,可以用QueryParser()轉換成小寫。

使用反轉Token的方法允許通配符出現在開頭。ReversedWildcardsTokenFilter可以實現Token反轉。ReversedWildcardsTokenFilter返回原來的Token和反轉的Token,其中反轉的Token的positionIncrement值是0。

可以用一個標識字符來避免正常Token和反轉Token之間的沖突。例如:“DNA”反轉后就變成“and”了,和正常的詞“and”有沖突。但是使用標識字符后,“DNA”就變成了“\u0001and”。

可以把ReversedWildcardsTokenFilter加入分析器鏈,這樣在做索引的時候就可以使用了。

有些英文單詞需要查詢擴展,如搜索“dog”的同時查找“dogs”。FuzzyQuery()有限狀態查詢(Finite-State Query)用編輯距離衡量相似度,例如“dog”和“dogs”的編輯距離是1。FuzzyQuery()內部使用編輯距離有限狀態機實現,所以性能很好。

        int maxEdits = 2;  //編輯距離最多不能超過2
        new FuzzyQuery(new Term("title", "dog"), maxEdits);

可以設置相同前綴的長度。例如,相同前綴的長度是1:

        FuzzyQuery query = new FuzzyQuery(new Term("field", "WEBER"), 2, 1);

query要求匹配的詞必須以W開頭,而且匹配的詞與查詢詞之間的編輯距離不超過2。這個FuzzyQuery等價于如下的有限狀態自動機:

        LevenshteinAutomata builder = new LevenshteinAutomata("EBER", true);
        Automaton a = builder.toAutomaton(2); //最大編輯距離是2
        Automaton b = BasicAutomata.makeChar('W'); //創建一個字符W組成的自動機
        Automaton c = BasicOperations.concatenate(b, a); //連接兩個自動機b和a

這里的BasicOperations.concatenate()方法把b的結束狀態和a的開始狀態用空轉換連接起來,也就是按順序走過a中的狀態,然后走b中的狀態。例如,自動機b可以接收字符W,然后自動機a繼續接收EB,就可以結束了。這說明自動機c可以接收WEB。

測試自動機c可以接收哪些字符:

        System.out.println(BasicOperations.run(c, "WBR")); //輸出true
        System.out.println(BasicOperations.run(c, "WEB")); //輸出true
        System.out.println(BasicOperations.run(c, "WEBE")); //輸出true
        System.out.println(BasicOperations.run(c, "WEBER")); //輸出true

在中文人名中使用自動機:

        LevenshteinAutomata builder = new LevenshteinAutomata("杰倫", true);
        Automaton a = builder.toAutomaton(1); //最大編輯距離是1
        Automaton b = BasicAutomata.makeChar(’周’);
        Automaton c = BasicOperations.concatenate(b, a); //連接兩個自動機b和c
        System.out.println(BasicOperations.run(c, "周杰倫")); //匹配寫錯的人名

在中文人名中使用模糊查詢:

        FuzzyQuery query = new FuzzyQuery(new Term("field", "周杰倫"), 1, 1);

“dogs~”這樣的模糊查詢語法使用FuzzyQuery()。FuzzyQuery()還可以用于拼寫檢查。

可以根據Automaton對象構建AutomatonQuery。

        Term term= new Term("yourfield", "周~*");
        LevenshteinAutomata builder = new LevenshteinAutomata("杰倫", true);
        Automaton a = builder.toAutomaton(1); //最大編輯距離是1
        Automaton b = BasicAutomata.makeChar(’周’);
        Automaton c= BasicOperations.concatenate(b, a); //連接兩個自動機b和c
        AutomatonQuery query = new AutomatonQuery(term, c);

再給出一個星閉包的例子:

        //查詢的term表示,包含列
        Term term= new Term("yourfield", "bla~*");
        //對所有的和“bla”編輯距離在2以內的字符串構建一個確定性有限狀態自動機
        Automaton fuzzy = new LevenshteinAutomata("bla", false).toAutomaton(2);
        //串聯fuzzy和另外一個DFA等于"*"操作符,也就是星閉包
        Automaton fuzzyPrefix=
                    BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());
        //構建一個查詢,用它搜索以得到結果
        AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);

Lucene的NumericRangeQuery采用了Trie樹結構的索引,可以模仿NumericRangeQuery編寫字符串的前綴匹配實現。

主站蜘蛛池模板: 罗田县| 威海市| 平陆县| 城步| 石屏县| 合水县| 嵊泗县| 日喀则市| 冷水江市| 四川省| 页游| 淳安县| 汝南县| 搜索| 伊宁市| 崇左市| 本溪市| 南昌县| 桦甸市| 宁津县| 新干县| 泰和县| 乐都县| 三原县| 乌兰察布市| 晋中市| 雷山县| 绩溪县| 曲水县| 宕昌县| 鞍山市| 武城县| 滕州市| 湄潭县| 兴安盟| 临沭县| 佛学| 荆门市| 内丘县| 新泰市| 轮台县|