引言
前面介绍了一些Lucene的基本知识,但是不用代码实现总是觉得不踏实,下面我们就完成Lucene的基本操作;
第一、导入所需jar包
上面jar包是本文中所用到的示例所需的jar包
第二、创建索引
// 创建索引
@Test
public void testIndex() throws Exception {
// 第一步:创建一个java工程,并导入jar包。
// 第二步:创建一个indexwriter对象。
Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
// 创建索引分析器
Analyzer analyzer = new IKAnalyzer();// 官方推荐
// 当项目中有多个lucene包的时候,需要在下面指定使用的版本
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
IndexWriter indexWriter = new IndexWriter(directory, config);
// 1)指定索引库的存放位置Directory对象
// 2)指定一个分析器,对文档内容进行分析。
// 第三步:创建field对象,将field添加到document对象中。
File f = new File("D:\\Lucene");
// 获得路径下面的所有的文件
File[] listFiles = f.listFiles();
for (File file : listFiles) {
// 第三步创建document对象
Document document = new Document();
String file_name = file.getName();
// 创建域
Field fileNameField = new TextField("fileName", file_name, Store.YES);
long file_size = FileUtils.sizeOf(file);
Field fileSizeField = new LongField("fileSize", file_size, Store.YES);
// 文件路径
String file_path = file.getPath();
Field filePathField = new StoredField("filePath", file_path);
// 文件内容
String file_content = FileUtils.readFileToString(file);
Field fileContentField = new TextField("fileContent", file_content, Store.NO);
document.add(fileNameField);
document.add(fileSizeField);
document.add(filePathField);
document.add(fileContentField);
// 第四步 使用 indexwriter对象将docum对象写人索引库,此过程进行索引创建。并将索引和document对象写入索引库
indexWriter.addDocument(document);
}
// 第五步: 关闭indexwriter对象
indexWriter.close();
}
注意:D:\\temp\\index这个路径是 我们创建的索引存储的位置,如果此路径不存在,程序会自动创建
D:\\Lucene 这个路径是我需要搜索的文件所在的位置
我们可以通过lukeall-4.10.3.jar查看,请读者自行下载!
第三、搜索索引
// 搜索索引
@Test
public void testSearch() throws Exception {
// 第一步:创建一个Directory对象,也就是索引库存放的位置。
Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
// 第二步:创建一个indexReader对象,需要指定Directory对象。
IndexReader indexReader = DirectoryReader.open(directory);
// 第三步:创建一个indexsearcher对象,需要指定IndexReader对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// 第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。
Query query = new TermQuery(new Term("fileName", "quartz.txt"));
// 第五步:执行查询。
TopDocs topDocs = indexSearcher.search(query, 10);
// 第六步:返回查询结果。遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println(fileName);
// 文件内容
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println(fileSize);
// 文件路径
String filePath = document.get("filePath");
System.out.println(filePath);
System.out.println("------------");
}
indexReader.close();
}
这里需要注意:创建索引和搜索时所用的分词器必须一致(才能匹配)
为了更好的展示我们的基本操作代码,我们讲创建indexSearcher对象的代码和查看查询结果的代码抽离
// 抽离创建indexSearcher对象的代码
public IndexSearcher getIndexSearcher() throws Exception {
Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
IndexReader indexReader = DirectoryReader.open(directory);
return new IndexSearcher(indexReader);
}
// 抽离执行查询结果的代码
public void printResult(IndexSearcher indexSearcher, Query query) throws Exception {
// 第五步:执行查询。
TopDocs topDocs = indexSearcher.search(query, 10);
// 第六步:返回查询结果。遍历查询结果并输出。
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
int doc = scoreDoc.doc;
Document document = indexSearcher.doc(doc);
// 文件名称
String fileName = document.get("fileName");
System.out.println(fileName);
// 文件内容
String fileContent = document.get("fileContent");
System.out.println(fileContent);
// 文件大小
String fileSize = document.get("fileSize");
System.out.println(fileSize);
// 文件路径
String filePath = document.get("filePath");
System.out.println(filePath);
System.out.println("------------");
}
}
下面展示几种基本查询:
// 查询所有的资源
@Test
public void testMatchAllDocsQuery() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
Query query = new MatchAllDocsQuery();
System.out.println(query);
printResult(indexSearcher, query);
indexSearcher.getIndexReader().close();
}
// 根据数值范围查询
@Test
public void testNumericRangeQuery() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
Query query = NumericRangeQuery.newLongRange("fileSize", 47L, 200L, false, true);
System.out.println(query);
printResult(indexSearcher, query);
// 关闭资源
indexSearcher.getIndexReader().close();
}
// 组合条件查询
@Test
public void testBooleanQuery() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
BooleanQuery booleanQuery = new BooleanQuery();
Query query1 = new TermQuery(new Term("fileName", "apache"));
Query query2 = new TermQuery(new Term("fileName", "lucene"));
booleanQuery.add(query1, Occur.MUST);
booleanQuery.add(query2, Occur.SHOULD);
printResult(indexSearcher, booleanQuery);
// 关闭资源
indexSearcher.getIndexReader().close();
}
// 条件查询
@Test
public void testQueryParser() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
// 参数1:默认查询域
// 参数2 采用分析器
QueryParser queryParser = new QueryParser("fileName", new IKAnalyzer());
// *:* 域:值
Query query = queryParser.parse("fileName:paache AND fileName:lucene");
printResult(indexSearcher, query);
// 关闭资源
indexSearcher.getIndexReader().close();
}
// 条件解析的对象查询 多个默认域
@Test
public void testMultiFieldQueryParser() throws Exception {
IndexSearcher indexSearcher = getIndexSearcher();
String[] fields = { "fileName", "fileContent" };
// 参数1: 默认查询的域
// 参数2:采用的分析器
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
// *:* 域:值
Query query = queryParser.parse("lucene is apache");
printResult(indexSearcher, query);
// 关闭资源
indexSearcher.getIndexReader().close();
}
第四、删除和修改
抽离创建IndexWriter对象的代码
public IndexWriter getIndexWriter() throws Exception {
// 第一步:创建一个java工程,并导入jar包。
// 第二步:创建一个indexwriter对象。
Directory directory = FSDirectory.open(new File("D:\\temp\\index"));
Analyzer analyzer = new StandardAnalyzer();// 官方推荐
IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, analyzer);
return new IndexWriter(directory, config);
}
// 根据条件删除
@Test
public void testDelete() throws Exception {
IndexWriter indexWriter = getIndexWriter();
Query query = new TermQuery(new Term("fileName", "lucene.txt"));
indexWriter.deleteDocuments(query);
indexWriter.close();
}
// 修改
@Test
public void testUpdate() throws Exception {
IndexWriter indexWriter = getIndexWriter();
Document doc = new Document();
doc.add(new TextField("fileN", "测试文件名", Store.YES));
doc.add(new TextField("fileC", "测试文件内容", Store.YES));
indexWriter.updateDocument(new Term("fileName", "quartz.txt"), doc, new IKAnalyzer());
indexWriter.close();
}
修改的本质就是增加,如果document存在则是修改的操作结果,若果document不存在则是增加的操作结果
小结
上面是基于Lucene的对应document的操作,我们可看出来这个的过程非常的麻烦,所以说如果我们在实际项中采用这个方案,会非常的影响开发效率,就好像我们采用原生servlet来开发java项目一样,所以这就需要一个框架来简化这个开发过程,于是solr就出现了。你说是“时势造英雄”呢?还是“英雄造时势”呢?下篇博客讲解solr的基本知识!