Lucene入门教程(一)

本文介绍 Lucene 4.5 的基本概念,包括如何为文档建立索引和搜索索引文件。通过实际代码示例展示了如何使用 Java API 创建索引,并演示了如何查询已建立的索引。

Lucene 4.5,document详解,例子实现,方法重写。

在这里分享一下Lucene的学习,主要参考官网上的一下教程和PDF版的《Lucene In Action》。当然,博客中很多内容都是摘自上面两个地方。


1. 什么是Lucene

        Lucene是一个高性能的、可扩展的信息检索工具。你可以把它融入到应用程序中以增加索引和搜索功能。Lucene是一个纯Java实现的成熟、自由、开源的软件项目。

它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。


官方网站:http://lucene.apache.org/

CSDN下载地址:http://download.csdn.net/detail/jolingogo/6472385


2. 索引和搜索

        使用Lucene,需要理解索引和搜索这两个概念。

索引:为了快速搜索大量文本文件,首先必须为文件建立索引,就像为一本书建立目录,然后把文本转换成你能够快速搜索到的格式,

而不是使用那种慢速顺序扫描的处理法。这个转换过程就叫做索引操作(indexing),他的输出就称为索引文件(index)。

        可以把索引想象成一种数据结构,这种数据结构允许对存储在其中的单词进行快速随机存取。


搜索:是在一个索引中查找关键字的过程,这个过程的目的是为了找到这些关键字在哪些地方出现过。

        搜索的质量通常有查确率(precise)和查全率(recall)来衡量。查全率可以衡量这个搜索系统查找到相关文档的能力,

而查确率则是用来衡量搜索系统过滤非相关文档的能力。


3. 第一个示例

准备工作:

1.新建2个文件夹

Lucene_data 里面,我新建了几个txt文本文件

Lucene_index用来存放索引

2. pom.xml

  1.     <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
            <modelVersion>4.0.0</modelVersion>  
          
            <groupId>org.ygy</groupId>  
            <artifactId>lucene</artifactId>  
            <version>0.0.1-SNAPSHOT</version>  
            <packaging>jar</packaging>  
          
            <name>lucene</name>  
            <url>http://maven.apache.org</url>  
          
            <properties>  
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
            </properties>  
          
            <dependencies>  
                <dependency>  
                    <groupId>junit</groupId>  
                    <artifactId>junit</artifactId>  
                    <version>4.10</version>  
                    <scope>test</scope>  
                </dependency>  
          
                <!-- Lucene依赖包 -->  
                <dependency>  
                    <groupId>org.apache.lucene</groupId>  
                    <artifactId>lucene-core</artifactId>  
                    <version>4.5.1</version>  
                </dependency>  
          
                <dependency>  
                    <groupId>org.apache.lucene</groupId>  
                    <artifactId>lucene-analyzers-icu</artifactId>  
                    <version>4.5.1</version>  
                </dependency>  
          
                <dependency>  
                    <groupId>org.apache.lucene</groupId>  
                    <artifactId>lucene-queryparser</artifactId>  
                    <version>4.5.1</version>  
                </dependency>  
          
          
            </dependencies>  
        </project>  


3.1 建立索引
  1. package org.ygy.lucene;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.FileNotFoundException;  
  7. import java.io.IOException;  
  8. import java.io.InputStreamReader;  
  9. import java.util.Date;  
  10.   
  11. import org.apache.lucene.analysis.Analyzer;  
  12. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  13. import org.apache.lucene.document.Document;  
  14. import org.apache.lucene.document.Field;  
  15. import org.apache.lucene.document.LongField;  
  16. import org.apache.lucene.document.StringField;  
  17. import org.apache.lucene.document.TextField;  
  18. import org.apache.lucene.index.IndexWriter;  
  19. import org.apache.lucene.index.IndexWriterConfig;  
  20. import org.apache.lucene.index.Term;  
  21. import org.apache.lucene.store.Directory;  
  22. import org.apache.lucene.store.FSDirectory;  
  23. import org.apache.lucene.util.Version;  
  24.   
  25. /** 
  26.  * 建立索引 
  27.  *  
  28.  * @author yuguiyang 
  29.  *  
  30.  */  
  31. public class IndexFiles {  
  32.   
  33.     // -index F:\Lucene_index -docs F:\Lucene_data  
  34.     public static void main(String[] args) {  
  35.         String usage = "java org.apache.lucene.demo.IndexFiles [-index INDEX_PATH] [-docs DOCS_PATH] [-update]\n\nThis indexes the documents in DOCS_PATH, creating a Lucene indexin INDEX_PATH that can be searched with SearchFiles";  
  36.   
  37.         String indexPath = "index"// 索引存放的路径  
  38.         String docsPath = null// 需要给哪些文件建立索引(即资源库的地址)  
  39.         boolean create = true// 是否新建索引  
  40.         for (int i = 0; i < args.length; i++) {  
  41.             if ("-index".equals(args[i])) {  
  42.                 indexPath = args[(i + 1)];  
  43.                 i++;  
  44.             } else if ("-docs".equals(args[i])) {  
  45.                 docsPath = args[(i + 1)];  
  46.                 i++;  
  47.             } else if ("-update".equals(args[i])) {  
  48.                 create = false;  
  49.             }  
  50.         }  
  51.   
  52.         if (docsPath == null) {  
  53.             System.err.println("Usage: " + usage);  
  54.             System.exit(1);  
  55.         }  
  56.   
  57.         // 验证资源文件地址  
  58.         File docDir = new File(docsPath);  
  59.         if ((!docDir.exists()) || (!docDir.canRead())) {  
  60.             System.out.println("Document directory '" + docDir.getAbsolutePath()  
  61.                     + "' does not exist or is not readable, please check the path");  
  62.             System.exit(1);  
  63.         }  
  64.   
  65.         // 开始建立索引  
  66.         Date start = new Date();  
  67.         try {  
  68.             System.out.println("Indexing to directory '" + indexPath + "'...");  
  69.   
  70.             // 根据索引存放地址,创建目录  
  71.             Directory dir = FSDirectory.open(new File(indexPath));  
  72.             // 初始化分析器  
  73.             Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);  
  74.             //索引配置  
  75.             IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_45, analyzer);  
  76.   
  77.             if (create) {  
  78.                 iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE);  
  79.             } else {  
  80.                 iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);  
  81.             }  
  82.   
  83.             //初始化索引  
  84.             IndexWriter writer = new IndexWriter(dir, iwc);  
  85.             indexDocs(writer, docDir);  
  86.   
  87.             //关闭索引  
  88.             writer.close();  
  89.   
  90.             Date end = new Date();  
  91.             System.out.println(end.getTime() - start.getTime() + " total milliseconds");  
  92.         } catch (IOException e) {  
  93.             System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());  
  94.         }  
  95.     }  
  96.   
  97.     //递归的方式,遍历每一个文件  
  98.     static void indexDocs(IndexWriter writer, File file) throws IOException {  
  99.         if (file.canRead())  
  100.             if (file.isDirectory()) {  
  101.                 String[] files = file.list();  
  102.   
  103.                 if (files != null)  
  104.                     for (int i = 0; i < files.length; i++)  
  105.                         indexDocs(writer, new File(file, files[i]));  
  106.             } else {  
  107.                 FileInputStream fis;  
  108.                 try {  
  109.                     fis = new FileInputStream(file);  
  110.                 } catch (FileNotFoundException fnfe) {  
  111.                     return;  
  112.                 }  
  113.   
  114.                 try {  
  115.                     Document doc = new Document();  
  116.   
  117.                     Field pathField = new StringField("path", file.getPath(), Field.Store.YES);  
  118.                     doc.add(pathField);  
  119.   
  120.                     doc.add(new LongField("modified", file.lastModified(), Field.Store.NO));  
  121.   
  122.                     doc.add(new TextField("contents"new BufferedReader(new InputStreamReader(fis, "UTF-8"))));  
  123.   
  124.                     if (writer.getConfig().getOpenMode() == IndexWriterConfig.OpenMode.CREATE) {  
  125.                         System.out.println("adding " + file);  
  126.                         writer.addDocument(doc);  
  127.                     } else {  
  128.                         System.out.println("updating " + file);  
  129.                         writer.updateDocument(new Term("path", file.getPath()), doc);  
  130.                     }  
  131.                 } finally {  
  132.                     fis.close();  
  133.                 }  
  134.             }  
  135.     }  
  136. }  

好了,虽然,上面的代码还不是很明白,但是,运行一下先。

运行时,需要指定一些参数:


运行结果:


好了,索引建立成功了,看一下,F:\Lucene_index文件夹

这些文件具体是什么,不太清楚,暂且当做是索引文件吧。

3.2 搜索
  1. package org.ygy.lucene;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.File;  
  5. import java.io.FileInputStream;  
  6. import java.io.IOException;  
  7. import java.io.InputStreamReader;  
  8. import java.util.Date;  
  9.   
  10. import org.apache.lucene.analysis.Analyzer;  
  11. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  12. import org.apache.lucene.document.Document;  
  13. import org.apache.lucene.index.DirectoryReader;  
  14. import org.apache.lucene.index.IndexReader;  
  15. import org.apache.lucene.queryparser.classic.QueryParser;  
  16. import org.apache.lucene.search.IndexSearcher;  
  17. import org.apache.lucene.search.Query;  
  18. import org.apache.lucene.search.ScoreDoc;  
  19. import org.apache.lucene.search.TopDocs;  
  20. import org.apache.lucene.store.FSDirectory;  
  21. import org.apache.lucene.util.Version;  
  22.   
  23. public class SearchFiles {  
  24.       
  25.     public static void main(String[] args) throws Exception {  
  26.         //对参数的一些处理  
  27.         String usage = "Usage:\tjava org.apache.lucene.demo.SearchFiles [-index dir] [-field f] [-repeat n] [-queries file] [-query string] [-raw] [-paging hitsPerPage]\n\nSee http://lucene.apache.org/core/4_1_0/demo/ for details.";  
  28.   
  29.         if ((args.length > 0) && (("-h".equals(args[0])) || ("-help".equals(args[0])))) {  
  30.             System.out.println(usage);  
  31.             System.exit(0);  
  32.         }  
  33.   
  34.         String index = "index";  
  35.         String field = "contents";  
  36.         String queries = null;  
  37.         int repeat = 0;  
  38.         boolean raw = false;  
  39.         String queryString = null;  
  40.         int hitsPerPage = 10;  
  41.   
  42.         for (int i = 0; i < args.length; i++) {  
  43.             if ("-index".equals(args[i])) {  
  44.                 index = args[(i + 1)];  
  45.                 i++;  
  46.             } else if ("-field".equals(args[i])) {  
  47.                 field = args[(i + 1)];  
  48.                 i++;  
  49.             } else if ("-queries".equals(args[i])) {  
  50.                 queries = args[(i + 1)];  
  51.                 i++;  
  52.             } else if ("-query".equals(args[i])) {  
  53.                 queryString = args[(i + 1)];  
  54.                 i++;  
  55.             } else if ("-repeat".equals(args[i])) {  
  56.                 repeat = Integer.parseInt(args[(i + 1)]);  
  57.                 i++;  
  58.             } else if ("-raw".equals(args[i])) {  
  59.                 raw = true;  
  60.             } else if ("-paging".equals(args[i])) {  
  61.                 hitsPerPage = Integer.parseInt(args[(i + 1)]);  
  62.                 if (hitsPerPage <= 0) {  
  63.                     System.err.println("There must be at least 1 hit per page.");  
  64.                     System.exit(1);  
  65.                 }  
  66.                 i++;  
  67.             }  
  68.         }  
  69.           
  70.         //读取索引  
  71.         IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(index)));  
  72.         //查询索引  
  73.         IndexSearcher searcher = new IndexSearcher(reader);  
  74.         //分析器  
  75.         Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_45);  
  76.   
  77.         BufferedReader in = null;  
  78.         if (queries != null)  
  79.             in = new BufferedReader(new InputStreamReader(new FileInputStream(queries), "UTF-8"));  
  80.         else {  
  81.             in = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));  
  82.         }  
  83.         //解析器  
  84.         QueryParser parser = new QueryParser(Version.LUCENE_45, field, analyzer);  
  85.         while (true) {  
  86.             if ((queries == null) && (queryString == null)) {  
  87.                 System.out.println("Enter query: ");  
  88.             }  
  89.   
  90.             String line = queryString != null ? queryString : in.readLine();  
  91.   
  92.             if ((line == null) || (line.length() == -1)) {  
  93.                 break;  
  94.             }  
  95.             line = line.trim();  
  96.             if (line.length() == 0) {  
  97.                 break;  
  98.             }  
  99.             Query query = parser.parse(line);  
  100.             System.out.println("Searching for: " + query.toString(field));  
  101.   
  102.             if (repeat > 0) {  
  103.                 Date start = new Date();  
  104.                 for (int i = 0; i < repeat; i++) {  
  105.                     searcher.search(query, null100);  
  106.                 }  
  107.                 Date end = new Date();  
  108.                 System.out.println("Time: " + (end.getTime() - start.getTime()) + "ms");  
  109.             }  
  110.   
  111.             doPagingSearch(in, searcher, query, hitsPerPage, raw, (queries == null) && (queryString == null));  
  112.   
  113.             if (queryString != null) {  
  114.                 break;  
  115.             }  
  116.         }  
  117.         reader.close();  
  118.     }  
  119.   
  120.     public static void doPagingSearch(BufferedReader in, IndexSearcher searcher, Query query, int hitsPerPage,  
  121.             boolean raw, boolean interactive) throws IOException {  
  122.         TopDocs results = searcher.search(query, 5 * hitsPerPage);  
  123.         ScoreDoc[] hits = results.scoreDocs;  
  124.   
  125.         int numTotalHits = results.totalHits;  
  126.         System.out.println(numTotalHits + " total matching documents");  
  127.   
  128.         int start = 0;  
  129.         int end = Math.min(numTotalHits, hitsPerPage);  
  130.         while (true) {  
  131.             if (end > hits.length) {  
  132.                 System.out.println("Only results 1 - " + hits.length + " of " + numTotalHits  
  133.                         + " total matching documents collected.");  
  134.                 System.out.println("Collect more (y/n) ?");  
  135.                 String line = in.readLine();  
  136.                 if ((line.length() == 0) || (line.charAt(0) == 'n')) {  
  137.                     break;  
  138.                 }  
  139.                 hits = searcher.search(query, numTotalHits).scoreDocs;  
  140.             }  
  141.   
  142.             end = Math.min(hits.length, start + hitsPerPage);  
  143.   
  144.             for (int i = start; i < end; i++) {  
  145.                 if (raw) {  
  146.                     System.out.println("doc=" + hits[i].doc + " score=" + hits[i].score);  
  147.                 } else {  
  148.                     Document doc = searcher.doc(hits[i].doc);  
  149.                     String path = doc.get("path");  
  150.                     if (path != null) {  
  151.                         System.out.println(i + 1 + ". " + path);  
  152.                         String title = doc.get("title");  
  153.                         if (title != null)  
  154.                             System.out.println("   Title: " + doc.get("title"));  
  155.                     } else {  
  156.                         System.out.println(i + 1 + ". " + "No path for this document");  
  157.                     }  
  158.                 }  
  159.             }  
  160.   
  161.             if ((!interactive) || (end == 0)) {  
  162.                 break;  
  163.             }  
  164.             if (numTotalHits >= end) {  
  165.                 boolean quit = false;  
  166.                 while (true) {  
  167.                     System.out.print("Press ");  
  168.                     if (start - hitsPerPage >= 0) {  
  169.                         System.out.print("(p)revious page, ");  
  170.                     }  
  171.                     if (start + hitsPerPage < numTotalHits) {  
  172.                         System.out.print("(n)ext page, ");  
  173.                     }  
  174.                     System.out.println("(q)uit or enter number to jump to a page.");  
  175.   
  176.                     String line = in.readLine();  
  177.                     if ((line.length() == 0) || (line.charAt(0) == 'q')) {  
  178.                         quit = true;  
  179.                         break;  
  180.                     }  
  181.                     if (line.charAt(0) == 'p') {  
  182.                         start = Math.max(0, start - hitsPerPage);  
  183.                         break;  
  184.                     }  
  185.                     if (line.charAt(0) == 'n') {  
  186.                         if (start + hitsPerPage >= numTotalHits)  
  187.                             break;  
  188.                         start += hitsPerPage;  
  189.                         break;  
  190.                     }  
  191.   
  192.                     int page = Integer.parseInt(line);  
  193.                     if ((page - 1) * hitsPerPage < numTotalHits) {  
  194.                         start = (page - 1) * hitsPerPage;  
  195.                         break;  
  196.                     }  
  197.                     System.out.println("No such page");  
  198.                 }  
  199.   
  200.                 if (quit)  
  201.                     break;  
  202.                 end = Math.min(numTotalHits, start + hitsPerPage);  
  203.             }  
  204.         }  
  205.     }  
  206. }  

哎,到目前为止,对上面的程序还不是很理解,但是可以跑通了,还不错,接着学习一下。

运行后,会提示,让你输入要查找的内容:

好了,目前之理解了这么多,先学一会儿,再接着分享哈。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值