、利用Lucene构建搜索引擎的一般过程:
各类文档的字符化——>对字符数据进行分词——>建立索引——>搜索(选择搜索字段、搜索方式,执行搜索)。
2、Lucene文件系统说明:
%LUCENE_HOME%\contrib\:Lucene扩展包,包括针对多种语言的分词工具、亮亮显示、Ant、xml文件解析等。其他目录无需赘言,清晰明了。
3、Lucene主要包结构:
|__org.apache.lucene.document:用于描述组成索引结构的文档和字段,索引结构类似数据库中的表,故索引结构中Document代表一行,Field代表字段,包内同时还定义了FieldSelector接口,以及其实现类,用来描述读取索引时哪些字段被读入程序。
|__org.apache.lucene.analysis:定义了一系列将各类文档转化为字符串所使用到的工具,主要包括了分词器、过滤器,以及亮亮显示中常用到的标记(Token)。Lucene在这个包之下定义了standard包,其中定义了对英文字符的标志分词器StandardAnalyzer,其他语言种类的分词器则在%LUCENE_HOME%\contrib\analyzers中定义(Lucene的扩展包)。过滤器用于在建立索引之时根据规则将文档中一些信息过滤掉,如英文中的a、an、is。
|__org.apache.lucene.index:用于维护和访问索引,常用的如IndexWriter用于组织Document并将其写入索引文件;IndexReader用于读出索引文件(以被检索);IndexModifier用于修改索引文件。同时,还定义了对索引和索引结构的维护类。
|__org.apache.lucene.queryParser:这个包由JavaCC( 详细介绍)自动生成。常用类是QueryParser,功能是利用分词器(必须与创建索引文件时用到的分词器相同)对查询关键字进行解析,解析产生一个Query对象,此对象交给Searcher类实例进行查询。
|__org.apache.lucene.search:执行查询,以及对查询结果的操作。主要使用到Query定义一个查询;IndexSearcher执行一个查询;TopScoreCollector传入查询参数,用以接收查询结果。
4、各类文档的字符化:
1)PDF---PDFBox,从 http://sourceforge.net/projects/pdfbox/下载PDFBox类库并解压,将external和lib下的jar包全copy到你的应用程序/lib下
2)WORD---用POI的一个组件包,textmining,从[url]http://mirrors.ibiblio.org/pub/mirrors/maven2/org/textmining/tm- extractors/0.4/[/url]下载tm-extractors-0.4.zip
3)EXCEL---JExcel,从 http://www.andykhan.com/jexcelapi/下载
4)XML---DOM4J,从 http://www.dom4j.org/下载
5)HTML---HTMLParser,从 http://htmlparser.sourceforge.net/下载,我们需要filterbuilder.jar,htmlparser.jar,htmllexer.jar,thumbelina.jar
6)Lius,用于从各种文档中提取文本信息,只是对PPT文档,只能解析出英文
5、建立索引:
Field定义:
Field.Store.YES:存储字段值(未分词前的字段值)
Field.Store.NO:不存储,存储与索引没有关系
Field.Store.COMPRESS:压缩存储,用于长文本或二进制,但性能受损
Field.Index.ANALYZED:分词建索引
Field.Index.ANALYZED_NO_NORMS:分词建索引,但是Field的值不像通常那样被保存,而是只取一个byte,这样节约存储空间
Field.Index.NOT_ANALYZED:不分词且索引
Field.Index.NOT_ANALYZED_NO_NORMS:不分词建索引,Field的值去一个byte保存
TermVector表示文档的条目(由一个Document和Field定位)和它们在当前文档中所出现的次数
Field.TermVector.YES:为每个文档(Document)存储该字段的TermVector
Field.TermVector.NO:不存储TermVector
Field.TermVector.WITH_POSITIONS:存储位置
Field.TermVector.WITH_OFFSETS:存储偏移量
Field.TermVector.WITH_POSITIONS_OFFSETS:存储位置和偏移量
6、搜索
7、多条件查询:
我们在实际应用中常常会对同时不同索引文件、不同字段进行搜索:对不同索引文件的查询主要通过定义多个Searcher,然后将它们集合到MulitSearcher中,利用MultiSearcher(实现类)的实例执行搜索操作;对不同字段的索引通过定义字段的数组,然后利用QueryParser解析数组。
1)多索引文件搜索:
方法一:这个搜索的结果可能有相同的信息,比如你有一条相同的信息在多个目录中索引,搜索的结果就会出现多次相同的信息。
方法二: 这个搜索是对搜索后的结果进行合并,剔除重复的信息。
2)多字段搜索:
方法一:利用booleanQuery添加多个Query,每个Query对应查询关键字与其中一个字段的对应Query
方法二:利用MultiFieldQueryParser将一个查询关键字关联到多个字段上
各类文档的字符化——>对字符数据进行分词——>建立索引——>搜索(选择搜索字段、搜索方式,执行搜索)。
2、Lucene文件系统说明:
%LUCENE_HOME%\contrib\:Lucene扩展包,包括针对多种语言的分词工具、亮亮显示、Ant、xml文件解析等。其他目录无需赘言,清晰明了。
3、Lucene主要包结构:
|__org.apache.lucene.document:用于描述组成索引结构的文档和字段,索引结构类似数据库中的表,故索引结构中Document代表一行,Field代表字段,包内同时还定义了FieldSelector接口,以及其实现类,用来描述读取索引时哪些字段被读入程序。
|__org.apache.lucene.analysis:定义了一系列将各类文档转化为字符串所使用到的工具,主要包括了分词器、过滤器,以及亮亮显示中常用到的标记(Token)。Lucene在这个包之下定义了standard包,其中定义了对英文字符的标志分词器StandardAnalyzer,其他语言种类的分词器则在%LUCENE_HOME%\contrib\analyzers中定义(Lucene的扩展包)。过滤器用于在建立索引之时根据规则将文档中一些信息过滤掉,如英文中的a、an、is。
|__org.apache.lucene.index:用于维护和访问索引,常用的如IndexWriter用于组织Document并将其写入索引文件;IndexReader用于读出索引文件(以被检索);IndexModifier用于修改索引文件。同时,还定义了对索引和索引结构的维护类。
|__org.apache.lucene.queryParser:这个包由JavaCC( 详细介绍)自动生成。常用类是QueryParser,功能是利用分词器(必须与创建索引文件时用到的分词器相同)对查询关键字进行解析,解析产生一个Query对象,此对象交给Searcher类实例进行查询。
|__org.apache.lucene.search:执行查询,以及对查询结果的操作。主要使用到Query定义一个查询;IndexSearcher执行一个查询;TopScoreCollector传入查询参数,用以接收查询结果。
4、各类文档的字符化:
1)PDF---PDFBox,从 http://sourceforge.net/projects/pdfbox/下载PDFBox类库并解压,将external和lib下的jar包全copy到你的应用程序/lib下
2)WORD---用POI的一个组件包,textmining,从[url]http://mirrors.ibiblio.org/pub/mirrors/maven2/org/textmining/tm- extractors/0.4/[/url]下载tm-extractors-0.4.zip
3)EXCEL---JExcel,从 http://www.andykhan.com/jexcelapi/下载
4)XML---DOM4J,从 http://www.dom4j.org/下载
5)HTML---HTMLParser,从 http://htmlparser.sourceforge.net/下载,我们需要filterbuilder.jar,htmlparser.jar,htmllexer.jar,thumbelina.jar
6)Lius,用于从各种文档中提取文本信息,只是对PPT文档,只能解析出英文
5、建立索引:
- final String IDNEX_PATH = "D:/Temp/lucene/index";//索引存放目录
- Analyzer analyzer = new PaodingAnalyzer();
- //利用索引目录及分词器构建索引写入器,true表示重新创建
- IndexWriter writer = new IndexWriter(IDNEX_PATH, analyzer,true,
- IndexWriter.MaxFieldLength.UNLIMITED);
- //创建文档,并添加字段
- Document doc = new Document();
- Field field = new Field("content", "Hello World~",Field.Store.YES,
- Field.Index.ANALYZED,Field.TermVector.WITH_POSITIONS_OFFSETS);
- doc.add(field);
- writer.addDocument(doc);//添加文档至索引中
- writer.optimize();//索引优化
- writer.close();//关闭写入,这一步必须执行,将缓存写入文件系统中
Field定义:
Field.Store.YES:存储字段值(未分词前的字段值)
Field.Store.NO:不存储,存储与索引没有关系
Field.Store.COMPRESS:压缩存储,用于长文本或二进制,但性能受损
Field.Index.ANALYZED:分词建索引
Field.Index.ANALYZED_NO_NORMS:分词建索引,但是Field的值不像通常那样被保存,而是只取一个byte,这样节约存储空间
Field.Index.NOT_ANALYZED:不分词且索引
Field.Index.NOT_ANALYZED_NO_NORMS:不分词建索引,Field的值去一个byte保存
TermVector表示文档的条目(由一个Document和Field定位)和它们在当前文档中所出现的次数
Field.TermVector.YES:为每个文档(Document)存储该字段的TermVector
Field.TermVector.NO:不存储TermVector
Field.TermVector.WITH_POSITIONS:存储位置
Field.TermVector.WITH_OFFSETS:存储偏移量
Field.TermVector.WITH_POSITIONS_OFFSETS:存储位置和偏移量
6、搜索
- final String field = "content";//定义将要在哪个字段上查询
- StandardAnalyzer analyzer = new StandardAnalyzer();
- QueryParser parser = new QueryParser(field, analyzer);//定义解析器
- IndexReader reader = IndexReader.open("D:\\Temp\\lucene\\index");//读入索引文件
- //执行查询
- IndexSearcher searcher = new IndexSearcher(reader);
- TopDocCollector topCollector = new TopDocCollector(100);//定义查询结果集,最多显示100条结果记录
- BufferedReader in = new BufferedReader(new
- InputStreamReader(System.in,"UTF-8"));
- String line = in.readLine();//读入查询关键字
- Query query = parser.parse(line);//利用解析器解析查询关键字,返回Query对象
- searcher.search(query, topCollector);//执行查询操作
- ScoreDoc[] scoreDocs = topCollector.topDocs().scoreDocs;//返回附带评分机制的结果集数组
- System.out.println("Found " + scoreDocs.length + " results in:");
- //遍历结果集,得到每个文档,然后对文档对性进行自定义操作
- for(ScoreDoc scoreDoc : scoreDocs){
- Document doc = searcher.doc(scoreDoc.doc);
- System.out.println("Path:\t" + doc.get("path"));
- }
7、多条件查询:
我们在实际应用中常常会对同时不同索引文件、不同字段进行搜索:对不同索引文件的查询主要通过定义多个Searcher,然后将它们集合到MulitSearcher中,利用MultiSearcher(实现类)的实例执行搜索操作;对不同字段的索引通过定义字段的数组,然后利用QueryParser解析数组。
1)多索引文件搜索:
方法一:这个搜索的结果可能有相同的信息,比如你有一条相同的信息在多个目录中索引,搜索的结果就会出现多次相同的信息。
- IndexSearcher searcher1 = new IndexSearcher(INDEX_PATH1);
- IndexSearcher searcher2 = new IndexSearcher(INDEX_PATH2);
- IndexSearcher[] searchers = {searcher1,searcher2};
- MultiSearcher multisearcher = new MultiSearcher(searchers);
- TopDocs multitopdocs = multisearcher.Search(query, null, 1000);
方法二: 这个搜索是对搜索后的结果进行合并,剔除重复的信息。
- IndexSearcher searcher1 = new IndexSearcher(INDEX_PATH1);
- IndexSearcher searcher2 = new IndexSearcher(INDEX_PATH2);
- IndexSearcher[] searchers = {searcher1,searcher2};
- ParallelMultiSearcher parallelmultisearcher = new ParallelMultiSearcher(searchers);
- TopDocs paralleltopdocs = parallelmultisearcher.Search(query, null, 1000);
2)多字段搜索:
方法一:利用booleanQuery添加多个Query,每个Query对应查询关键字与其中一个字段的对应Query
- final String[] field_list = {"pk_dept","deptname","depttype","deptduty","addr","tel"};
- String keyword = "Sales";
- BooleanQuery boolQuery = new BooleanQuery();
- for(String field : field_list){
- QueryParser parser = new QueryParser(field,new PaodingAnalyzer());
- Query query = parser.parse(keyword);
- //boolQuery集合了多个query,
- //参数BooleanClause.Occur.SHOULD:可以满足添加的query所定义的条件,即可能在该field中检索
- //参数BooleanClause.Occur.SHOULD:必须满足添加的query所定义的条件,即必须在该field中检索
- boolQuery.add(query,BooleanClause.Occur.SHOULD);
- }
- searcher.search(boolQuery, topCollector);
方法二:利用MultiFieldQueryParser将一个查询关键字关联到多个字段上
- final String[] field_list = {"pk_dept","deptname","depttype","deptduty","addr","tel"};
- String keyword = "Sales";
- QueryParser multi_parser = new MultiFieldQueryParser(field_list,new PaodingAnalyzer());
- Query query = multi_parser.parse(keyword);
- searcher.search(query,topCollector);