Lucene 快速入门
2016-05-16 14:30
525 查看
Lucene 简介
Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 6.0.0 demo API
要想快速入门最快的学习方法就是看官方 demo 文档。所需要的 jar 包:
lucene-core-{version}.jar
lucene-queryparser-{version}.jar
lucene-analyzers-common-{version}.jar
lucene-demo-{version}.jar
建立索引
全文搜索之所以如此的迅速就是因为搜索是在索引库中进行,将所需搜索的内容建立索引并以文件的形式保存。Lucene 提供了五个基本类来建立索引:
Document
Document 是用来描述文档的,一个 Document 对象由多个 Field 对象组成。
Field
Field 对象是用来描述文档的某个属性的。可以把一个 Document 对象比喻成数据库中的一条记录,Field 是这个记录的字段,例如一个 File 对象的路径和文本内容可以用两个 Field 对象分别描述。
Analyzer
分词器。在一个文档被索引之前,首先需要对文档内容进行分词处理。
IndexWriter
IndexWriter 是 Lucene 用来创建索引的一个核心类,它的作用是把一个个的 Document 对象加到索引库中来。
Directory
处理索引的存储位置。
样例 IndexFiles.java 对文本文档建立索引。
public static void main(String[] args) { // 索引存放目录 String indexPath = "index"; String docsPath = "需要索引的目录"; final Path docDir = Paths.get(docsPath); Date start = new Date(); try { System.out.println("Indexing to directory '" + indexPath + "'..."); Directory dir = FSDirectory.open(Paths.get(indexPath)); Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig iwc = new IndexWriterConfig(analyzer); IndexWriter writer = new IndexWriter(dir, iwc); indexDocs(writer, docDir); writer.close(); Date end = new Date(); System.out.println(end.getTime() - start.getTime() + " total milliseconds"); } catch (IOException e) { System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage()); } } /** * 对每个文件进行索引 * @param writer 存储索引 * @param path 需要索引的文件或目录 * / static void indexDocs(final IndexWriter writer, Path path) throws IOException { // 如果是目录就遍历 if (Files.isDirectory(path)) { Files.walkFileTree(path, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { try { indexDoc(writer, file, attrs.lastModifiedTime().toMillis()); } catch (IOException ignore) { // 如果文件不能读取不影响下一个文件的索引 } return FileVisitResult.CONTINUE; } }); } else { indexDoc(writer, path, Files.getLastModifiedTime(path).toMillis()); } } /** * 设置索引内容 */ static void indexDoc(IndexWriter writer, Path file, long lastModified) throws IOException { try (InputStream stream = Files.newInputStream(file)) { Document doc = new Document(); // 构造器 StringField(String name, String value, Field.Store stored) // StringField 索引但不分词, 也就是会把这个字符串当成一个完整的词来进行索引. // Field.Store 是否存储 Field pathField = new StringField("path", file.toString(), Field.Store.YES); doc.add(pathField); // 构造器 TextField(String name, Reader reader) // TextField 索引分词 doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)))); // OpenMode.CREATE 创建新索引或覆盖已有索引 // OpenMode.CREATE_OR_APPEND 将索引添加进已有索引, 如果不存在旧索引就创建新索引 if (writer.getConfig().getOpenMode() == OpenMode.CREATE) { System.out.println("adding " + file); writer.addDocument(doc); } else { System.out.println("updating " + file); writer.updateDocument(new Term("path", file.toString()), doc); } } }
搜索
文本文档建立好索引后,就可以在索引上进行搜索啦。Lucene 提供了四个基本类来进行搜索:
IndexSearch
IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。
Query
这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。
TopDocs
存储 IndexSearcher.search(Query,int) 返回的结果集。
ScoreDoc
将 TopDocs 数据处理成所需的 hits。
样例 SearchFiles.java 进行搜索
public static void main(String[] args) throws Exception { // 索引目录 String index = "index"; // 要搜索的字段 String field = "contents"; String queries = null; String queryString = null; // 需要显示的结果数 int hitsPerPage = 10; IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(index))); IndexSearcher searcher = new IndexSearcher(reader); Analyzer analyzer = new StandardAnalyzer(); BufferedReader in = null; in = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8)); QueryParser parser = new QueryParser(field, analyzer); while (true) { if (queries == null && queryString == null) { // prompt the user System.out.println("Enter query: "); } String line = queryString != null ? queryString : in.readLine(); if (line == null || line.length() == -1) { break; } line = line.trim(); if (line.length() == 0) { break; } Query query = parser.parse(line); System.out.println("Searching for: " + query.toString(field)); TopDocs results = searcher.search(query, hitsPerPage); ScoreDoc[] hits = results.scoreDocs; int numTotalHits = results.totalHits; System.out.println(numTotalHits + " total matching documents"); for(int i=0;i<hits.lengt a3c3 h;i++){ Document doc = searcher.doc(hits[i].doc); System.out.println(doc.get("path")); } if (queryString != null) { break; } } reader.close(); }
以上是对文本内容进行搜索,如果需要搜索目录,只需修改 Document 和 Field
// 构造器 TextField(String name, String value, Field.Store store) doc.add(new TextField("path",file.toString(),Field.Store.YES)); String field = "path";
相关文章推荐
- Spring (3.2.4) 常用jar 包解析
- Xmanager连接 Linux 6的配置
- Storyboard学习五(简单注册页面实现)
- 01背包专题
- BestCoder Round #83 1001&&HDU-5680 zxa and set (水)
- springmvc + hibernate + mysql + maven 简单应用
- QT-Demo-Colck-01
- Bootstrap4一次重大更新 几乎涉及每行代码
- HTTP 消息结构
- mac升级到10.11后使用CocoaPod出现-bash: pod: command not found 解决办法
- C++第10/11周项目 继承与派生 【项目4- 教师兼干部类】(复习新版)
- WCF NetTcpBinding.ReaderQuotas.MaxDepth 引用异常故障排除
- 02 Struts2开发环境的搭建和第一个Struts2应用开发
- inline 内联函数的使用
- [算法][C]计算向量的角度
- 通讯录的实现(二)动态实现
- 夜半对话
- 线性表的操作 (2.2) C = A U B
- android应用换肤功能的实现
- RT3070 网卡移植