Lucene 入门详解

一. 索引

1. 索引流程

获取内容(爬虫等) —>

建立文档(获取内容转换成文档:标题、 征文、 摘要、 作者、 链接。 加权), 借助 Tika 框架可以方便地从 PDF、 Word 等中方便提取 —>

文档分析 (文本分割成语汇单元的独立原子元素, 和语言中的单词很像。 如何处理连接一体的各个单词呢?   是否需要进行语法修正? 是否需要插入同义词? 是否需要将单数和复数格式单词合并成同一个语汇单元? 常用词干提取器, running, run, runs 映射到 run) —>

文档索引 (文档加入索引列表)

2. 索引核心类

IndexWriter 是索引过程的核心组件。 可以理解为: 提供对索引文件的写入操作, 但不能用于读取或者搜索索引。 IndexWriter 需要开辟一定空间来存储索引, 该功能可以由 Directory 完成。

Director 类描述了 Lucene 索引的存放位置。

Analyzer 负责从索引文本文件中提取语汇单元, 并提出剩下的无用信息。

Document 对表一些 Field 的集合。 可以理解为虚拟文档 - 比如 Web 页面、 Email 信息或者文本文件, 然后可以从中获取大量数据。

3. 索引调试

使用 IndexWriter 的 setInfoStream(System.out)  该代码能够揭示有关段刷新和段合并的诊断信息, 可以帮助我们调整索引参数。  也可以使用 Luck 第三方工具来监视。

二. 搜索

1. 搜索流程

搜索质量主要由查准率(过滤非相关文档能力)和查全率(查找相关文档的能力)来衡量。

用户搜索界面:直观、 简洁。 最好的例子当然是 Google。 高亮关键词, 排序都至关重要 —>

建立查询(Build Query): Lucene 提供了一个称之为查询解析器(QueryParser)的强大开发包, 用它可以根据通用查询语法(布尔运算、 短语查询、 通配符)将用户输入的文本处理成查询对象。 在这期间, 也可以进行加权或者过滤, 如电商过滤掉脱销产品防止客户流到其他电商。 —>

搜索查询(Search Query): 查询检索索引并返回与查询语句匹配的文档, 结果返回时按照查询请求来排序。

常见搜索理论模型:

纯布尔模型 — 文档不管是否匹配查询请求, 都不会被评分。 即无序的, 仅是匹配文档的一个集合。

向量空间模型 — 查询语句和文档都是高维空间向量模型, 每一个独立项都是一个维度。 查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到。

概率模型  采用全概率方法来计算文档和查询语句的匹配概率。

Lucene 并没有提供有关搜索范围的处理模块。 但 Solr 和 Nutch 都提供了对索引拆分和复制。 Katta 也能提供。 Elastic search 提供了另一个选择。

2. 搜索核心类

IndexSearcher 类用于搜索由 IndexWriter 类创建的索引。 最简单的搜索方法将单个 Query 对象和 int topN 计数作为参数, 返回一个 TopDocs 对象。

Term 搜索功能基本单元。

Query Lucene 含有 Query 的子类。 TermQuery, BooleanQuery、 PhraseQuery、 PrefixQuery、 PhrasePrefixQuery、 TermRangeQuery、 NumericRangeQuery、 FilteredQuery 和 SpanQuery。

三. 代码实战

import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;

/**
 * Lucene 检索内存索引
 *
 * @author wenniuwuren
 *
 */
public class LuceneTest {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();  

        // 新建一个内存目录对象
        Directory directory = new RAMDirectory();
        //Directory diskDirectory = new FSDirectory();

        //使用 IKAnalyzer 进行分词
        StandardAnalyzer analyzer = new StandardAnalyzer();
        IndexWriterConfig config = new IndexWriterConfig(analyzer);
        /*
         * 创建索引写入对象,该对象既可以把索引写入到磁盘中也可以写入到内存中。 参数说明:
         * directory:目录对象,也可以是FSDirectory 磁盘目录对象
         * config:分词器,分词器就是将检索的关键字分割成一组组词组,
         * 例子是 Lucene 自带的, 也可以使用第三方的分词器。
         */
        IndexWriter writer = new IndexWriter(directory, config);

        // 创建Document 文档对象,在lucene中创建的索引可以看成数据库中的一张表,
        // 表中也可以有字段,往里面添加内容之后可以根据字段去匹配查询
        // 下面创建的doc对象中添加了三个字段,分别为name,sex,dosomething
        Document doc = new Document();
        /*
        *  参数说明 public Field(String name, String value, Store store, Index index)
        *  name : 字段名称
        *  value : 字段的值
        *
        *  store :
        *  Field.Store.YES:存储字段值(未分词前的字段值)可以用 IndexReader 恢复。 对于需要展示搜索结果的一些域很有用(URL、 标题)
        *  Field.Store.NO:不存储,存储与索引没有关系。 通常跟 Index.ANALYZED 选项共同来索引大的文本, 通常这些不需要恢复初始格式, 如 Wbe 页面征文
        *  Field.Store.COMPRESS:压缩存储,用于长文本或二进制,但性能受损。 CPU 计算时间换空间
        *
        *  index : 建立索引的方式,是否建立分词等等
        *  Field.Index.ANALYZED:分词建索引, 使每个分词可以被索引
        *  Field.Index.NOT_ANALYZED:不分词但是索引。 适用于不能被分解的值: URL、 社保号等。 尤其适用于精确搜索。
        *  Field.Index.ANALYZED_NO_NORMS:分词建索引,不在索引中存储 norms 信息。 norms 记录了索引中的 index-time boost 信息, 搜索时比较耗费内存
        *  Field.Index.NOT_ANALYZED_NO_NORMS:与 Field.Index.NOT_ANALYZED 相似, 但也不存储 norms(加权基准)。通常用于搜索期间节省索引空间和减少内存耗费。
         * Field.Index.NO -- 使对应的值不能被搜索
        */
        doc.add(new Field("name", "wenniuwuren", Field.Store.YES,Field.Index.ANALYZED));
        doc.add(new Field("sex", "男性", Field.Store.YES,Field.Index.NOT_ANALYZED));
        doc.add(new Field("dosometing", "I am learning lucene ",Field.Store.YES, Field.Index.ANALYZED));
        // 文档对象加入索引
        writer.addDocument(doc);
        writer.close(); // 这里可以提前关闭,因为dictory 写入内存之后 与IndexWriter 没有任何关系了  

        // 因为索引放在内存中,所以存放进去之后要立马测试,否则,关闭应用程序之后就检索不到了
        // 创建IndexSearcher 检索索引的对象,里面要传递上面写入的内存目录对象directory

        // 打开索引文件  磁盘方式FSDirectory.open(new File()); IndexReader 开销较大, 建议搜友搜索期间使用同一个
        IndexReader reader =  DirectoryReader.open(directory);
        IndexSearcher searcher = new IndexSearcher(reader);

        // TermQuery 最基本的 Query 实现, 解析查询字符串
         Query query = new TermQuery(new Term("dosometing", "lucene"));
        // Query query = new TermQuery(new Term("sex", "男")); // 未分词, 搜索不到
        // Query query = new TermQuery(new Term("name", "wen"));  // 虽然分词了, 但是英文需要空格隔开才算一个分词, 搜索不到

        // 去索引目录中查询,返回的是 TopDocs 对象,里面存放的就是上面放的 document 文档对象的前(TOP)几个内容
        TopDocs result = searcher.search(query, 10);
        long endTime = System.currentTimeMillis();
        System.out.println("总共花费" + (endTime - startTime) + "毫秒,检索到" + result.totalHits + "条记录。");
        for (int i = 0; i < result.scoreDocs.length; i++) {
            Document document = searcher.doc(result.scoreDocs[i].doc);

            System.out.println("name:" + document.getField("name").stringValue());
            System.out.println("sex:" + document.getField("sex").stringValue());
            System.out.println("dosomething:" + document.getField("dosometing").stringValue());

            // 对搜索结果评分细节
            Explanation explanation = searcher.explain(query, result.scoreDocs[i].doc);
            System.out.println(explanation.toString());
        }
        writer.close();
        directory.close();
    }
}  

时间: 2024-11-16 03:22:19

Lucene 入门详解的相关文章

【转】Asp.Net MVC3 简单入门详解过滤器Filter

原文地址:http://www.cnblogs.com/boruipower/archive/2012/11/18/2775924.html 前言 在开发大项目的时候总会有相关的AOP面向切面编程的组件,而MVC(特指:Asp.Net MVC,以下皆同)项目中不想让MVC开发人员去关心和写类似身份验证,日志,异常,行为截取等这部分重复的代码,那我们可以通过AOP截取实现,而在MVC项目中我们就可以直接使用它提供的Filter的特性帮我们解决,不用自己实现复杂的AOP了. 在Asp.net Mvc

webpack入门详解

webpack入门详解(基于webpack 3.5.4  2017-8-22) webpack常用命令: webpack --display-error-details    //执行打包 webpack -w               // 提供watch方法:实时进行打包更新 webpack -p           // 对打包后的文件进行压缩 webpack -d            // 提供source map,方便调式代码 webpack -dev-server --open 

Quartz 入门详解

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的日程序表.Jobs可以做成标准的Java组件或 EJBs.官方网站:http://www.opensymphony.com/quartz 相关Jar:   quartz-all-1.6.0.jar   jta.jar   commons-logging-1.1.jar

Linq之旅:Linq入门详解(Linq to Objects)

示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集成查询).通过LINQ,我们可以使用相同API操作不同的数据源.接下来就让我们看看LINQ是什么以及如何使用? 再此之前,需要先了解的相关技术 1. 隐式类型.匿名类型.对象初始化器 1) 隐式类型,使用var关键字创建,C#编译器会根据用于初始化局部变量的初始值推断出变量的数据类型.(不过我个人认

SQL注入攻防入门详解(2)

SQL注入攻防入门详解 =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口.这几天把sql注入的相关知识整理了下,希望大家多多提意见. (对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉的犯下大错,专门查看大量前辈们的心得,这方面的资料颇多,将其精简出自己觉得重要的,就成了该文

[转]SQL注入攻防入门详解

原文地址:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口.这几天把sql注入的相关知识整理了下,希望大家多多提意见. (对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么

SQL注入攻防入门详解

原文地址:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机会接触相关开发……必须的各种借口.这几天把sql注入的相关知识整理了下,希望大家多多提意见. (对于sql注入的攻防,我只用过简单拼接字符串的注入及参数化查询,可以说没什么

【转载】SQL注入攻防入门详解

滴答…滴答…的雨,欢迎大家光临我的博客. 学习是快乐的,教育是枯燥的. 博客园  首页  博问  闪存    联系  订阅 管理 随笔-58 评论-2028 文章-5  trackbacks-0 站长统计|  今日IP[353] | 今日PV[848] | 昨日IP[922] |  昨日PV[2188] |当前在线[10] SQL注入攻防入门详解 =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但

JAVA定时任务调度之Timer入门详解(二)

在上篇的JAVA定时任务调度之Timer入门详解(一)文章中,主要介绍了下Timer,接下来我们一起来看看Timer的一些常用方法. 1.schedule()的4种用法. 第一种:schedule(TimerTask task, Date time); task:安排的任务,time:具体执行时间.这个函数表达的意义是:在时间等于或超过time的时候执行且执行一次task.测试内容如下 MyTimerTask.java的代码跟第一篇一样,MyTimer.java的部分代码截图如下: 运行后,控制