全文检索技术适合做各种网站的站内搜索,例如京东,淘宝等电商网站,是一门非常使用的技术,这里讲解其原生技术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.创建索引
*/
@Test
public 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.搜索索引
*/
@Test
public 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
*/
@Test
public 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.删除全部索引
*
*/
@Test
public void testDeleteAll() throws Exception {
// 1.1获取indexWriter对象
IndexWriter indexWriter=getIndexWriter();
// 1.2调用方法删除所有索引
indexWriter.deleteAll();
// 1.3关闭流
indexWriter.close();
}
/**
* 2.根据条件删除指定索引
* @throws Exception
*/
@Test
public 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
*/
@Test
public 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
*/
@Test
public 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
*/
@Test
public 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
*/
@Test
public 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
*/
@Test
public 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
*/
@Test
public 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("---------------------");
}
}
}
配置文件内容如下: