全文检索之lucene的使用(上)

来源:互联网 发布:c语言生成随机数 编辑:程序博客网 时间:2024/05/16 10:24

全文检索技术适合做各种网站的站内搜索,例如京东,淘宝等电商网站,是一门非常使用的技术,这里讲解其原生技术lucene的使用,在全文检索之lucene的使用(下)讲讲解框架solr的使用,lucene的jar下载地址:http://lucene.apache.org/
以下为代码实现:
package com.ilike.lucene;

import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
* 全文检索引擎lucene的使用 ①导入相应的jar包及配置文件包括如下 :
* commons-io-2.4.jar
* IKAnalyzer2012FF_u1.jar
* lucene-analyzers-common-4.10.3.jar
* lucene-analyzers-smartcn-4.10.3.jar
* lucene-core-4.10.3.jar
* lucene-queryparser-4.10.3.jar
*
* IKAnalyzer.cfg.xml
* ext.dic(需要识别的新词)
* stopword.dic(不需要创建索引的词)
*
* @author 桑伟东
*
*/

public class LuceneDemo1 {

/* * 1.创建索引 */@Testpublic void testCreateIndex1() throws Exception {    // 1.1 创建一个indexWriter对象    Directory directory = FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));    // Analyzer analyzer=new    // StandardAnalyzer();//该分析器是apache官方推介使用,但是只适合分析英文    Analyzer analyzer = new IKAnalyzer();// 这是一个较为强大的中文分析器    IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST, analyzer);    IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);    // 1.2创建field对象,将field添加到document对象中    // 加载你要创建索引的文件    File file = new File("D:\\tmp\\lucene_temp_src");    File[] files = file.listFiles();    for (File file2 : files) {        // 1.3创建document对象        Document document = new Document();        // 1.3.1文件名称        String file_name = file2.getName();        Field fileNameField = new TextField("fileName", file_name, Store.YES);// YES表示存储在索引库中,反之则不存        // 1.3.2文件大小        Long file_size = FileUtils.sizeOf(file2);        Field fileSizeField = new LongField("fileSize", file_size, Store.YES);        // 1.3.3文件路径        String file_path = file2.getPath();        Field filePathField = new StoredField("filePath", file_path);        // 1.3.4文件内容        String file_content = FileUtils.readFileToString(file2);        Field fileContentField = new TextField("fileContent", file_content, Store.NO);        // 1.3.5将域对象添加到document中        document.add(fileNameField);        document.add(fileSizeField);        document.add(filePathField);        document.add(fileContentField);        // 1.4使用indexWriter对象将document对象写入文档库        indexWriter.addDocument(document);    }    // 1.5关闭indexWriter对象    indexWriter.close();}/* * 2.搜索索引 */@Testpublic void testSearchIndex1() throws Exception {    // 2.1创建Directory对象,也就是索引库的位置    Directory directory = FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));    // 2.2创建indexReader对象,需要制定Directory    IndexReader indexReader = DirectoryReader.open(directory);    // 2.3创建indexSearch对象,需要制定IndexReader    IndexSearcher indexSearcher = new IndexSearcher(indexReader);    // 2.4创建一个TearmQuery对象,指定查询的域和查询的关键词    Query query = new TermQuery(new Term("fileN", "文件名"));    // 2.5执行查询    TopDocs topDocs = indexSearcher.search(query, 10);    // 2.6返回查询结果,遍历查询结果并输出    ScoreDoc[] scoreDocs = topDocs.scoreDocs;    for (ScoreDoc scoreDoc : scoreDocs) {        int docId = scoreDoc.doc;        Document document = indexSearcher.doc(docId);        // 文件名称        String file_name = document.get("fileName");        System.out.println(file_name);        // 文件内容        String file_content = document.get("fileContent");        System.out.println(file_content);        // 文件大小        String file_size = document.get("fileSize");        System.out.println(file_size);        // 文件路径        String file_path = document.get("filePath");        System.out.println(file_path);        System.out.println("---------------------");    }    // 2.7关闭indexReader对象    indexReader.close();}/** * 可以挑选不同的分析器查看不同的分词效果,IKAnalyzer分词器目前最适合分析中文 如果有新词出现,可添加到配置文件ext.dic中 *  * @throws Exception */@Testpublic void testTokenStream() throws Exception {    // 创建一个标准分析器对象    // Analyzer analyzer = new StandardAnalyzer();    // Analyzer analyzer = new CJKAnalyzer();    // Analyzer analyzer = new SmartChineseAnalyzer();    Analyzer analyzer = new IKAnalyzer();    // 获得tokenStream对象    // 第一个参数:域名,可以随便给一个    // 第二个参数:要分析的文本内容    // TokenStream tokenStream = analyzer.tokenStream("test",    // "The Spring Framework provides a comprehensive programming and    // configuration model.");    TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据");    // 添加一个引用,可以获得每个关键词    CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);    // 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置    OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);    // 将指针调整到列表的头部    tokenStream.reset();    // 遍历关键词列表,通过incrementToken方法判断列表是否结束    while (tokenStream.incrementToken()) {        // 关键词的起始位置        System.out.println("start->" + offsetAttribute.startOffset());        // 取关键词        System.out.println(charTermAttribute);        // 结束位置        System.out.println("end->" + offsetAttribute.endOffset());    }    tokenStream.close();}

}

package com.ilike.lucene;

import java.io.File;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

/**
* 索引管理(增加,修改,删除,查询)
* 增加:入门程序类LuceneDemo1已写过
* 修改:
* 删除:
* 查询:入门程序类LuceneDemo1已写过精准查询
* 查询方式:①子类查询:只需要按照查询需求,挑选Query的子类即可
* ②解析查询:需要写语法,可打印子类查询中的query对象,了解语法
* @author 桑伟东
*
*
*/

public class LuceneManager {

/*1.删除全部索引 *  */@Testpublic void testDeleteAll() throws Exception {    // 1.1获取indexWriter对象    IndexWriter indexWriter=getIndexWriter();    // 1.2调用方法删除所有索引    indexWriter.deleteAll();    // 1.3关闭流    indexWriter.close();}/** * 2.根据条件删除指定索引 * @throws Exception */@Testpublic void testDeleteByCondition() throws Exception {    // 2.1获取indexWriter对象    IndexWriter indexWriter=getIndexWriter();    // 2.2创建查询条件(fileName中名字中带有apache的索引)    Query query=new TermQuery(new Term("fileName", "apache"));    // 2.3调用方法删除指定索引    indexWriter.deleteDocuments(query);    // 2.4关闭流    indexWriter.close();}/** * 3.修改索引的方法 * @throws Exception */@Testpublic void testUpdateByCondition() throws Exception {    // 3.1获取indexWriter对象    IndexWriter indexWriter=getIndexWriter();    // 3.2创建要新增的索引    Document document=new Document();    document.add(new TextField("fileN", "测试文件名1", Store.YES));    document.add(new TextField("fileC", "测试文件1的内容", Store.YES));    // 3.3调用方法修改指定的索引(第一个参数中的内容会被删除,第二个参数是要新增的内容,第三个参数是中文词法分析器对象)    indexWriter.updateDocument(new Term("fileName", "apache"), document, new IKAnalyzer());    // 3.4关闭流    indexWriter.close();}/** * 4.查询所有 * @throws Exception */@Testpublic void testQueryAll() throws Exception {    // 4.1获取IndexSearcher对象    IndexSearcher indexSearcher=getIndexSearcher();    // 4.2创建一个MatchAllDocsQuery对象    Query query=new MatchAllDocsQuery();    // 4.3执行查询并打印查询结果    printQueryResult( query, indexSearcher);    // 4.4关闭资源    indexSearcher.getIndexReader().close();}/** * 5.根据数值范围查询 * @throws Exception */@Testpublic void testQueryByCondition() throws Exception {    // 5.1获取IndexSearcher对象    IndexSearcher indexSearcher=getIndexSearcher();    // 5.2创建一个NumericRangeQuery对象,("fileSize"表示域,       //20l表示最小值,1000l表示最大值,false表示不包含20,true表示包含1000    Query query=NumericRangeQuery.newLongRange("fileSize", 20l, 1000l, false, true);    // 5.3执行查询并打印查询结果    printQueryResult( query, indexSearcher);    // 5.4关闭资源    indexSearcher.getIndexReader().close();}/** * 6.多条件组合查询 * @throws Exception */@Testpublic void testQueryByConditions() throws Exception {    // 5.1获取IndexSearcher对象    IndexSearcher indexSearcher=getIndexSearcher();    // 5.2创建组合查询的条件    BooleanQuery booleanQuery=new BooleanQuery();    Query query1=new TermQuery(new Term("fileName", "java"));    Query query2=NumericRangeQuery.newLongRange("fileSize", 10l, 100000l, false, true);    // 5.3执行查询并打印查询结果(MUST表示条件必须满足,MUST_NOT表示不满足,SHOULD表示可以没有)    booleanQuery.add(query1, Occur.MUST);    booleanQuery.add(query2, Occur.MUST);    printQueryResult( booleanQuery, indexSearcher);    // 5.4关闭资源    indexSearcher.getIndexReader().close();}/** * 1.条件解析的对象查询 * @throws Exception  */@Testpublic void testParserQuery() throws Exception {    // 1.1获取IndexSearcher对象    IndexSearcher indexSearcher=getIndexSearcher();    // 1.2创建查询的条件,默认查询的域是fileName    QueryParser queryParser=new QueryParser("fileName", new IKAnalyzer());    //Query query=queryParser.parse("*:*");// *:*代表     域:值,写法可以参照上文的查询,打印上文查询中的query对象就可知道    Query query=queryParser.parse("apache");//表示查询默认fileName域的apache    printQueryResult( query, indexSearcher);    // 1.4关闭资源    indexSearcher.getIndexReader().close();}/** * 2.条件解析的对象查询(多个默认查询域) * @throws Exception  */@Testpublic void testParserQuery2() throws Exception {    // 1.1获取IndexSearcher对象    IndexSearcher indexSearcher=getIndexSearcher();    // 1.2创建查询的条件,默认查询的域是fileName和fileContent    String [] fields={"fileName","fileContent"};    MultiFieldQueryParser multiFieldQueryParser=new MultiFieldQueryParser(fields, new IKAnalyzer());    //Query query=queryParser.parse("*:*");// *:*代表     域:值    Query query=multiFieldQueryParser.parse("apache is java");//表示查询默认fileName域的apache    printQueryResult( query, indexSearcher);    // 1.4关闭资源    indexSearcher.getIndexReader().close();}/** * 抽取获得IndexWriter的方法 * @return * @throws Exception */private IndexWriter getIndexWriter() throws Exception {    // 1.1 创建一个indexWriter对象    Directory directory =FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));    Analyzer  analyzer=new StandardAnalyzer();    IndexWriterConfig indexWriterConfig=new IndexWriterConfig(Version.LATEST, analyzer);    return new IndexWriter(directory, indexWriterConfig);}/** * 抽取获得IndexSearcher的方法 * @return * @throws Exception */private IndexSearcher getIndexSearcher() throws Exception {    // 2.1创建Directory对象,也就是索引库的位置    Directory directory =FSDirectory.open(new File("D:\\tmp\\lucene_indexRes"));    // 2.2创建indexReader对象,需要制定Directory    IndexReader indexReader=DirectoryReader.open(directory);    // 2.3创建indexSearch对象,需要制定IndexReader    return new IndexSearcher(indexReader);}private void printQueryResult(Query query,IndexSearcher indexSearcher) throws Exception {    // 2.5执行查询            TopDocs  topDocs =indexSearcher.search(query, 10);            // 2.6返回查询结果,遍历查询结果并输出            ScoreDoc [] scoreDocs=  topDocs.scoreDocs;             for (ScoreDoc scoreDoc : scoreDocs) {                  int docId=scoreDoc.doc;                Document document=indexSearcher.doc(docId);                //文件名称                String file_name1=document.get("fileName");                System.out.println(file_name1);                //文件内容                String file_content1=document.get("fileC");                System.out.println(file_content1);                //文件大小                String  file_size=document.get("fileSize");                System.out.println(file_size);                //文件路径                String file_path=document.get("filePath");                System.out.println(file_path);                System.out.println("---------------------");             }}

}

配置文件内容如下: