`
mengqingyu
  • 浏览: 333109 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

Lucene 详解

阅读更多
1.什么是全文检索
        对于搜索,按被搜索的资源类型,分为两种:可以转为文本的、多媒体类型。我们上一节提到的搜索功能都是搜索的可以转为文本的资源(第一种)。注意,百度或谷歌提供的音乐或视频搜索不是多媒体搜索,他们是按文件名搜索。在智能手机上有一款音乐搜索的软件,可以让他听10秒钟的音乐,然后他就能上网找出这段音乐的名称、演奏者等信息。这是多媒体搜索。
        按搜索的方式,上一节提到的搜索功能都是不处理语义,只是找出包含指定词的所有资源(只对词进行匹配)。下图就是显示“中国的首都是哪里”这个搜索要求对应的结果,可以看到,是没有“北京”这个结果的,结果页面都是出现了这些词的网页:
全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。全面、准确和快速是衡量全文检索系统的关键指标。
关于全文检索,我们要知道:1,只处理文本。2,不处理语义。3,搜索时英文不区分大小写。4,结果列表有相关度排序。
        在信息检索工具中,全文检索是最具通用性和实用性的。
全文检索不同于数据库的SQL查询。(他们所解决的问题不一样,解决的方案也不一样,所以不应进行对比)。在数据库中的搜索就是使用SQL,如:SELECT * FROM t WHERE content like ‘%ant%’。这样会有如下问题:
1.匹配效果:如搜索ant会搜索出planting。这样就会搜出很多无关的信息。
2.相关度排序:查出的结果没有相关度排序,不知道我想要的结果在哪一页。我们在使用百度搜索时,一般不需要翻页,为什么?因为百度做了相关度排序:为每一条结果打一个分数,这条结果越符合搜索条件,得分就越高,叫做相关度得分,结果列表会按照这个分数由高到低排列,所以第1页的结果就是我们最想要的结果。
3.全文检索的速度大大快于SQL的like搜索的速度。这是因为查询方式不同造成的,以查字典举例:数据库的like就是一页一页的翻,一行一行的找,而全文检索是先查目录,得到结果所在的页码,再直接翻到这一页。

2.使用Lucene的API操作索引库
        索引库是一个目录,里面是一些二进制文件,就如同数据库,所有的数据也是以文件的形式存在文件系统中的。我们不能直接操作这些二进制文件,而是使用Lucene提供的API完成相应的操作,就像操作数据库应使用SQL语句一样。
        对索引库的操作可以分为两种:管理与查询。管理索引库使用IndexWriter,从索引库中查询使用IndexSearcher。Lucene的数据结构为Document与Field。Document代表一条数据,Field代表数据中的一个属性。一个Document中有多个 Field,Field的值为String型,因为Lucene只处理文本。
        我们只需要把在我们的程序中的对象转成Document,就可以交给Lucene管理了,搜索的结果中的数据列表也是Document的集合。
        有了这些概念,可以写HelloWorld了,其他的概念可以在写完HelloWorld后再进行说明。

3.环境
要加入的jar包有:
lucene-core-3.0.1.jar(核心包)
contrib\analyzers\common\lucene-analyzers-3.0.1.jar(分词器)
contrib\highlighter\lucene-highlighter-3.0.1.jar(高亮)
contrib\memory\lucene-memory-3.0.1.jar(高亮)

4.核心类
索引核心类
1、IndexWriter(写索引)
2、Directory(索引存放位置)
3、Analyzer(分析器)
4、document(文档)
5、Field(域)

搜索核心类
1、IndexSearcher(搜索引)
2、Term(搜索功能基本单元)
3、Query(查询)
4、TermQuery(Query 子类 最基本查询类型)
5、TopDocs(指针容器)

IndexWriter
IndexWriter是在索引过程中的中心组件。这个类创建一个新的索引并且添加文档到一个已有的索引中。
它可以对索引进行添、删、更新操作,但是不能读取或搜索。

添加方法
addDocument (Document)加Document使用默认的分词器
addDocument (Document, Analyzer)加入的时候使用指定的分词器

删除方法
deleteDocuments (Term);
deleteDocuments (Term[]);
deleteDocuments (Query);
deleteDocuments (Query[]);
一般最好有个唯一索引,这样才好删,不然的话有可以会一删一大堆
如:writer.deleteDocument(new Term(“ID”, documentID));

更新方法
注意:更新索引也提供两个方法,其实Lucene是没有办法更新的,只有先删除了再更新,
updateDocument (Term, Document);
如:writer.updateDocument(new Term(“ID”, documenteId), newDocument);
updateDocument (Term, Document, Analyzer)

5.实例
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.*;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

public class SqlCon {
	public static void main(String[] args) {
		Date date1 = new Date();
		String connectionUrl = "jdbc:sqlserver://localhost:1433;"
				+ "databaseName=pubs;user=sa;password=";
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			con = DriverManager.getConnection(connectionUrl);
			String SQL = "SELECT TOP 10 * FROM users";
			stmt = con.createStatement();
			rs = stmt.executeQuery(SQL);
			IndexWriter writer = new IndexWrite("C://index//",
					new StandardAnalyzer(), true);
			while (rs.next()) {
				Document doc = new Document();
				doc.add(new Field("id", rs.getString("id"), Field.Store.YES,
						Field.Index.TOKENIZED));
				doc.add(new Field("name", rs.getString("name"),
						Field.Store.YES, Field.Index.TOKENIZED));
				doc.add(new Field("sex", rs.getString("sex"), Field.Store.YES,
						Field.Index.TOKENIZED));
				doc.add(new Field("age", rs.getString("age"), Field.Store.YES,
						Field.Index.TOKENIZED));
				writer.addDocument(doc);
			}
			writer.close();
			Date date2 = new Date();
			System.out.println("用时" + (date2.getTime() - date1.getTime())
					+ "毫秒索引已建立");
			DoSearch();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (rs != null)
				try {
					rs.close();
				} catch (Exception e) {
				}
			if (stmt != null)
				try {
					stmt.close();
				} catch (Exception e) {
				}
			if (con != null)
				try {
					con.close();
				} catch (Exception e) {
				}
		}

	}

	public static void DoSearch() throws IOException, ParseException {
		IndexSearcher indexSearcher = new IndexSearcher("C://index//");// 和上面的IndexWriter一样是一个工具
		QueryParser queryParser = new QueryParser("name",
				new StandardAnalyzer());
		Query query = queryParser.parse("yxy");// 这个地方Query是抽象类大家也注意一下
		Hits hits = indexSearcher.search(query);
		// Document doc = null;
		System.out.print("正搜索................");
		System.out.println("找到了" + hits.length() + "个结果");
		for (int i = 0; i < hits.length(); i++) {
			Document doc = hits.doc(i);
			System.out.println("内容是:" + doc.get("name"));// 注意这里输出的是什么
		}
	}
}


6.高亮(Highlight)
需要的jar包为:
// 生成高亮器
Formatter formatter = newSimpleHTMLFormatter("<span class='kw'>", "</span>");
Scorer scorer = newQueryScorer(query);
Highlighter highlighter = newHighlighter(formatter, scorer);
highlighter.setTextFragmenter(newSimpleFragmenter(20));
// 使用高亮器:对content属性值进行摘要并高亮
Stringtext = highlighter.getBestFragment(LuceneUtils.getAnalyzer(),"content", doc.get("content"));
// 如果进行高亮的属性值中没有要搜索的关键字,则返回null
if (text != null) {
   doc.getField("content").setValue(text);
}

7.复合查询(多种查询条件的综合查询)
(1)联合两个索引查询,已解决:
IndexSearcher[] searchers = new IndexSearcher[2];  
searchers[0] = new IndexSearcher(m_indexpath); 
searchers[1] = new IndexSearcher(m_outindexpath); 
MultiSearcher multiSearcher = new MultiSearcher(searchers); 

(2)还有个进行多条件搜索 and 与 or 的操作————
用 MultiFieldQueryParser 建议重新封装
MultiFieldQueryParser.Parser(p[],d[],f[],analyer)
  成or 与 and操作合一 或者
BooleanQuery m_BooleanQuery = new BooleanQuery(); 
Query query = QueryParser.Parse(m_SearchText, "INSTRUMENT_NAME", analyzer); 
Query query2 = QueryParser.Parse(m_SearchText2, "INSTRUMENT_NAME2", analyzer); 
m_BooleanQuery.Add(query, true, false); 
m_BooleanQuery.Add(query2, true, false); 
(3)复合查询(多种查询条件的综合查询)
Query query=MultiFieldQueryParser.parse("索引”,new String[] {"title","content"},analyzer); 
Searcher searcher=new IndexSearcher(indexFilePath); 
Hits hits=searcher.search(query); 
for (int i = 0; i < hits.length(); i++)  { 
            System.out.println(hits.doc(i).get("name")); 
} 

8.为查询优化索引(index)
        Indexwriter.optimize()方法可以为查询优化索引(index),之前提到的参数调优是为indexing过程本身优化,而这里是为查询优化,优化主要是减少index文件数,这样让查询的时候少打开文件,优化过程中,lucene会拷贝旧的index再合并,合并完成以后删除旧的index,所以在此期间,磁盘占用增加, IO符合也会增加,在优化完成瞬间,磁盘占用会是优化前的2倍,在optimize过程中可以同时作search。

9.Lucene 的检索结果排序
        Lucene的排序主要是对org.apache.lucene.search.Sort的使用。Sort可以直接根据字段Field生成,也可以根据标准的SortField生成,但是作为Sort的字段,必须符合以下的条件:唯一值以及Indexed。可以对Integers, Floats, Strings三种类型排序。
        对整数型的ID检索结果排序只要进行以下的简单操作:
Sort sort = new Sort("id");
Hits hits = searcher.search(query, sort);
用户还可以根据自己定义更加复杂的排序,详细请参考API。

10.需要注意的问题
(1)IndexWriter在添加新的document后,需要重新建立Index,则需要调用writer.optimize();方法
(2)Lucene没有update索引的方法,需要删除后重新建立,参考remove方法
(3)用IndexReader删除Document后,需要重新用IndexWriter进行整理,否则无法在进行搜索(不知道是不是我设置问题)
(4)Lucene先在内存中进行索引操作,并根据一定的批量进行文件的写入。这个批次的间隔越大,文件的写入次数越少,但占用内存会很多。反之占用内存少,但文件IO操作频繁,索引速度会很慢。在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境的情况充分利用内存减少文件的操作。根据我的使用经验:缺省Indexer是每20条记录索引后写入一次,每将MERGE_FACTOR增加50倍,索引速度可以提高1倍左右。
(5)并发操作Lucene
所有只读操作都可以并发
在index被修改期间,所有只读操作都可以并发
对index修改操作不能并发,一个index只能被一个线程占用
index的优化,合并,添加都是修改操作
(6)Locking机制
lucence内部使用文件来locking,默认的locking文件放在java.io.tmpdir,可以通过-Dorg.apache.lucene.lockDir=xxx指定新的dir,有write.lock commit.lock两个文件,lock文件用来防止并行操作index,如果并行操作, lucene会抛出异常,可以通过设置-DdisableLuceneLocks=true来禁止locking,这样做一般来说很危险,除非你有操作系统或者物理级别的只读保证,比如把index文件刻盘到CDROM上。

参考:http://www.iteye.com/topic/582236
分享到:
评论

相关推荐

    Lucene开发详解.pdf

    ### Lucene开发详解 #### 一、Lucene简介 Lucene是一个高性能、全功能的文本搜索引擎库,由Doug Cutting创建并捐赠给Apache Software Foundation。它主要用于构建全文搜索应用程序,能够帮助开发者快速地在其应用...

    Lucene 全文检索 之 详解

    **全文检索技术与Lucene详解** 全文检索是一种在大量文本数据中快速查找包含特定词汇或短语的信息的技术。在互联网时代,随着数据量的爆炸性增长,高效、准确的全文检索变得至关重要。Lucene,由Apache软件基金会...

    \Lucene Nutch和安装说明文旦

    **Lucene详解** Apache Lucene是一个高性能、全文本搜索库,它提供了完整的搜索功能,包括分词、索引、搜索、评分和结果排序。Lucene的核心组件包括以下几个部分: 1. **分词器(Tokenizer)**: 将输入文本分割...

    Lucene+Nutch搜索光盘资料

    一、Lucene详解 Lucene的核心功能包括文本分析、索引构建、搜索和结果排序等。文本分析涉及分词、去除停用词、词干化等预处理步骤,使得文本更适合索引和搜索。索引构建通过倒排索引实现高效查询,将文档中的每个词...

    搜索引擎Lucene_资料

    **搜索引擎Lucene详解** 搜索引擎Lucene是Apache软件基金会下的一个开放源代码全文检索库,它提供了高效的、可扩展的文本搜索功能。Lucene的核心功能包括文档索引、搜索以及相关的排序算法,使得开发者能够轻松地在...

    Lucene 常用功能介绍视频详解

    **Lucene 常用功能介绍** Lucene 是一个高性能、全文检索库,由Apache软件基金会开发并维护。它提供了一个简单但功能强大的API,用于在各种应用中实现全文索引和搜索。以下是对Lucene常用功能的详细介绍: 1. **...

    全文检索(Lucene)详解

    **全文检索(Lucene)详解** Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发并维护。它提供了一个简单但功能强大的API,用于在各种数据源中进行高效的全文检索。Lucene不仅用于网站搜索引擎,还广泛...

    Java的全文索引引擎--Lucene.ppt

    **Java全文索引引擎——Lucene详解** Lucene是一个高性能、全文检索库,由Apache软件基金会开发并维护,是Java编程语言中最受欢迎的全文搜索引擎之一。它提供了强大的文本分析、索引构建和搜索功能,使得开发者能够...

    详解SpringBoot+Lucene案例介绍

    SpringBoot与Lucene集成案例详解 本文将详细介绍如何将SpringBoot与Lucene集成,以实现站内搜索系统。 Lucene是一个高性能的全文检索引擎,它可以帮助我们快速地检索大量的文本数据。 一、案例介绍 在本案例中,...

    Lucene 实时搜索视频详解

    在"Lucene 实时搜索视频详解"的课程中,我们将深入探讨如何利用 Lucene 实现高效且实时的搜索功能。 一、Lucene 基础 1. **索引过程**:Lucene 的核心概念之一是建立索引,将原始文本数据转化为可快速查询的结构。...

    lucene评分公式详解

    Lucene是一款强大的全文搜索引擎库,广泛应用于各种搜索应用中。它的核心功能之一是根据用户查询与文档的相关性进行打分,这个过程涉及到一个关键的概念——评分公式。本文将深入探讨Lucene的评分公式,理解其工作...

    Lucene 概述视频详解

    Lucene是一个开源全文搜索引擎库,由Apache软件基金会开发并维护。它提供了一个高度可扩展的基础架构,用于在大型文档集合中进行快速、高效的全文检索。在本视频教程中,我们将深入探讨Lucene的核心概念,以及如何...

    lucene、lucene.NET详细使用与优化详解

    《lucene、lucene.NET 详细使用与优化详解》 lucene 是一个广泛使用的全文搜索引擎库,其.NET版本称为lucene.NET,它提供了强大的文本检索和分析能力,适用于各种场景下的全文搜索需求。lucene 并非一个可以直接...

    Hibernate 与 Lucene 的整合框架详解

    ### Hibernate 与 Lucene 的整合框架详解 #### 一、概述 在软件开发领域,特别是企业级应用开发中,高效的数据检索与管理是至关重要的。Hibernate 和 Lucene 分别作为对象关系映射(ORM)工具和全文搜索引擎,在...

    Lucene分词与查询详解

    **Lucene分词与查询详解** Lucene是一个高性能、全文本搜索库,广泛应用于各种搜索引擎的开发中。它提供了一套强大的API,用于索引文本数据,并执行复杂的查询操作。在深入理解Lucene的分词与查询机制之前,我们...

    lucene搜索引擎配置详解

    Lucene是Apache软件基金会的一个开放源代码项目,它是一个全文搜索引擎库,提供了高效、可扩展的信息检索服务。本文将深入探讨Lucene搜索引擎的配置过程,包括文件加载、索引创建和搜索操作,帮助你理解其核心技术。...

    Lucene中文分词源码详解

    Lucene,作为一种全文搜索的辅助工具,为我们进行条件搜索,无论是像Google,Baidu之类的搜索引 擎,还是论坛中的搜索功能,还是其它C/S架构的搜索,都带来了极大的便利和比较高的效率。本文主要是利用Lucene对MS Sql...

    lucene文档笔记详解

    **Lucene文档笔记详解** Lucene,源自Apache软件基金会4 Jakarta项目组,是一个备受开发者青睐的开源全文检索引擎工具包。它提供了强大的文本分析、索引构建和搜索功能,但值得注意的是,Lucene本身并不包含完整的...

    Lucene3.0之查询类型详解

    【Lucene3.0查询类型详解】 在Lucene3.0中,查询处理是一个关键环节,涉及多种查询方式和理论模型。以下是对这些概念的详细解释: 1. **查询方式**: - **顺序查询**:是最简单的查询方式,直接遍历索引,效率较...

Global site tag (gtag.js) - Google Analytics