引言
前面介绍了一些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的基本知识!