lucene分词器与搜索
一、分词器
lucene针对不同的语言和虚伪提供了许多分词器,我们可以针对应用的不同的需求使用不同的分词器进行分词。我们需要注意的是在创建索引时使用的分词器与搜索时使用的分词器要保持一致。否则搜索的结果就不是我们期望的结果。lucene提供的常规分词器如下:
•StandardAnalyzer 标准分词器
•IKAnalyzer 基于Lucene的第三方中文分词技术
•WhitespaceAnalyzer 空格分词器
•SimpleAnalyzer 简单分词器
•CJKAnalyzer 二分法分词器
•KeywordAnalyzer 关键词分词器
•StopAnalyzer 被忽略词分词器
•FrenchAnalyzer 法国语言分词
•GermanAnalyzer 德国语言分词
•GreekAnalyzer 希腊语言分词
•RussianAnalyzer 俄罗斯语言分词
相关分词器示例如下:
1 package com.test.lucene; 2 3 import java.io.IOException; 4 import java.io.StringReader; 5 6 import org.apache.lucene.analysis.Analyzer; 7 import org.apache.lucene.analysis.TokenStream; 8 import org.apache.lucene.analysis.cjk.CJKAnalyzer; 9 import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer; 10 import org.apache.lucene.analysis.core.KeywordAnalyzer; 11 import org.apache.lucene.analysis.core.SimpleAnalyzer; 12 import org.apache.lucene.analysis.core.StopAnalyzer; 13 import org.apache.lucene.analysis.core.WhitespaceAnalyzer; 14 import org.apache.lucene.analysis.standard.StandardAnalyzer; 15 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; 16 17 /** 18 * 分词器 19 */ 20 public class AnalyzerStudy { 21 22 /** 23 * 分词并打印分词结果 24 * 25 * @param analyzer 26 * 分词器种类 27 * @param content 28 * 需要分词的内容 29 */ 30 private static void print(Analyzer analyzer, String content) { 31 StringReader reader = new StringReader(content); 32 try { 33 TokenStream tokenStream = analyzer.tokenStream("", reader); 34 tokenStream.reset(); 35 CharTermAttribute term = tokenStream.getAttribute(CharTermAttribute.class); 36 System.out.println("分词技术" + analyzer.getClass()); 37 while (tokenStream.incrementToken()) { 38 System.out.print(term.toString() + "|"); 39 } 40 System.out.println(); 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 } 45 46 public static void main(String[] args) { 47 String content = "上海广州, lucene 软件 开发"; 48 Analyzer analyzer = null; 49 // 标准分词 50 analyzer = new StandardAnalyzer(); 51 print(analyzer, content); 52 53 // 空格分词 54 analyzer = new WhitespaceAnalyzer(); 55 print(analyzer, content); 56 57 // 简单分词 58 analyzer = new SimpleAnalyzer(); 59 print(analyzer, content); 60 61 // 二分法分词 62 analyzer = new CJKAnalyzer(); 63 print(analyzer, content); 64 65 // 关键字分词 66 analyzer = new KeywordAnalyzer(); 67 print(analyzer, content); 68 69 // 被忽略词分词 70 analyzer = new StopAnalyzer(); 71 print(analyzer, content); 72 73 // 中文分词 74 analyzer = new SmartChineseAnalyzer(); 75 print(analyzer, content); 76 } 77 78 }
运行结果如下:
二、搜索条件
在有些应用场景中,我们需要在搜索的时候,使用多个条件进行查询。此时我们可以使用lucene提供的搜索条件进行搜索。如对多个域进行查询、前缀查询、通配符查询等。
相关示查询例如下:
1 package com.test.lucene; 2 3 import org.apache.lucene.analysis.Analyzer; 4 import org.apache.lucene.analysis.standard.StandardAnalyzer; 5 import org.apache.lucene.index.Term; 6 import org.apache.lucene.queryparser.classic.MultiFieldQueryParser; 7 import org.apache.lucene.queryparser.classic.ParseException; 8 import org.apache.lucene.queryparser.classic.QueryParser; 9 import org.apache.lucene.search.BooleanClause.Occur; 10 import org.apache.lucene.search.BooleanQuery; 11 import org.apache.lucene.search.PhraseQuery; 12 import org.apache.lucene.search.PrefixQuery; 13 import org.apache.lucene.search.Query; 14 import org.apache.lucene.search.TermQuery; 15 import org.apache.lucene.search.TermRangeQuery; 16 17 /** 18 * 查询条件 19 */ 20 public class QueryStudy { 21 public static void main(String[] args) { 22 // 搜索关键词 23 String keyword = "上海"; 24 // 搜索域名 25 String field = "name"; 26 // 搜索多个域的域名数组 27 String[] fields = { "name", "content" }; 28 // Query 创建过程中的分词技术 29 Analyzer analyzer = new StandardAnalyzer(); 30 Query query = null; 31 // 对单个域创建查询语句 32 QueryParser parser = new QueryParser(field, analyzer); 33 try { 34 query = parser.parse(keyword); 35 } catch (ParseException e) { 36 e.printStackTrace(); 37 } 38 System.out.println(QueryParser.class + " " + query.toString()); 39 40 // 对多个域创建查询语句 41 MultiFieldQueryParser parser2 = new MultiFieldQueryParser(fields, analyzer); 42 try { 43 query = parser2.parse(keyword); 44 } catch (ParseException e) { 45 e.printStackTrace(); 46 } 47 System.out.println(MultiFieldQueryParser.class + " " + query.toString()); 48 49 // 词条查询语句 50 query = new TermQuery(new Term(field, keyword)); 51 System.out.println(TermQuery.class + " " + query.toString()); 52 53 // 前缀查询语句 54 query = new PrefixQuery(new Term(field, keyword)); 55 System.out.println(PrefixQuery.class + " " + query.toString()); 56 57 // 多余查询语句 58 PhraseQuery query2 = new PhraseQuery(); 59 // 设置短语之间的最大距离 60 query2.add(new Term(field, "上海")); 61 query2.add(new Term(field, "lucene开发")); 62 System.out.println(PhraseQuery.class + " " + query2.toString()); 63 64 // 通配符查询语句,Lucene中有 * ? 两个通配符, *表示任意多个字符,?表示一个任意字符 65 query = TermRangeQuery.newStringRange(field, "abc", "azz", false, false); 66 System.out.println(TermRangeQuery.class + " " + query.toString()); 67 68 // 布尔查询 69 BooleanQuery query3 = new BooleanQuery(); 70 query3.add(new TermQuery(new Term(field, "上海")), Occur.SHOULD); 71 query3.add(new TermQuery(new Term(field, "lucene")), Occur.SHOULD); 72 query3.add(new TermQuery(new Term(field, "案例")), Occur.MUST_NOT); 73 System.out.println(BooleanQuery.class + " " + query3.toString()); 74 } 75 }
运行结果如下: