- 自己動手寫分布式搜索引擎
- 羅剛
- 1099字
- 2020-11-28 15:52:49
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編寫字符串的前綴匹配實現。
- RAW攝影后期從入門到精通:Photoshop+Lightroom雙修精解
- Irrlicht 1.7 Realtime 3D Engine Beginner's Guide
- Photoshop 2022從入門到精通
- 中文版3ds Max 2016/VRay效果圖制作實戰基礎教程
- 剪映專業版(電腦版)視頻剪輯全攻略:音效添加+轉場特效+視頻制作
- Oracle SQL Developer 2.1
- Photoshop CC 2017從入門到精通
- 中文版3ds Max 2016實用教程
- 中文版Photoshop 2020完全自學教程
- OpenCart 1.4 Template Design Cookbook
- Adobe Flash 11 Stage3D (Molehill) Game Programming Beginner's Guide
- 數碼攝影修圖師完全手冊(第2卷)
- Photoshop CC圖形圖像處理實戰教程(微課版)
- 中老年學微信(圖解大字版)
- 中文版SolidWorks 2016完全實戰技術手冊