`
sunqitang
  • 浏览: 76999 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

我理解的lucene原理(初级)

阅读更多

1 先上一段代码,分析最简单的lucene的Hello World代码

 

package cn.itcast.lesson;

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.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.Field.TermVector;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.junit.Test;

public class HelloWorld {
	String title = "IndexWriter.addDocument 's javadoc";
	String content = "Adds  a document to this index. If the document contains more than setMaxFieldLength(int) terms for a given field, the remainder are discarded.";

	String indexPath = "d:/luceneIndex_20100316/"; // 索引库所在的文件夹
	Analyzer analyzer = new StandardAnalyzer();    // 分词器

	/** 建立索引 */
	@Test
	public void createIndex() throws Exception {
		// 1,把对象转为Lucene的Document
		Document doc = new Document();
		
		Field field = new Field("title", title, Store.YES, Index.ANALYZED);
		Field field2 = new Field("content", content, Store.YES, Index.ANALYZED);
		doc.add(field);
		doc.add(field2);
		/**
		 * 上面代码分析:
		 * 其中创建了document,什么是document?在源码中我们发现,document中有一个名为field名称的List集合。
		 * 这个list里面存放的为Filed类型的数据。
		 * 每一个Field文件类似于Map文件,他有一个name和value值。value只接受字符串(非字符串类型要先转换成字符串才行)。
		 * 找到Field的构造函数 public Field(String name, String value, Store store, Index index, TermVector termVector)
		 * Store,指定Field是否或怎样存储。--- Store.NO,不存储。 Store.YES,存储。Store.COMPRESS,压缩后存储
		 * Index,指定Field是否或怎么被索引。----Index.NO,不索引(不索引就不能被搜索到)。Index.ANALYZED,分词后索引。Index.NOT_ANALYZED,不分词,直接索引(把整个Field值做为一个term)。
		 */
		
		
		// 2,把Document添加到索引库中
		IndexWriter indexWriter = new IndexWriter(indexPath, analyzer, MaxFieldLength.LIMITED);
		indexWriter.addDocument(doc);
		indexWriter.close();
		
		/**
		 * 上面代码分析:
		 * IndexWriter是Lucene用来创建索引的一个核心的类。使用构造方法IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl); 
		 * Directory,代表了 Lucene 的索引的存储的位置。这是一个抽象类,常用的有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引位置。
		 * Analyzer,在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给IndexWriter 来建立索引。
		 * MaxFieldLength,用于限制Field的大小。这个变量可以让用户有计划地对大文档Field进行截取。假如取值为10000,就只索引每个Field的前10000个Term(关键字)。也就是说每个Field中只有前10000个Term(关键字)建立索引,除此之外的部分都不会被Lucene索引,当然也不能被搜索到。
		 */
	}

	/** 搜索 */
	@Test
	public void search() throws Exception {
		String queryString = "document";

		IndexSearcher indexSearcher = new IndexSearcher(indexPath);

		QueryParser queryParser = new QueryParser("content", analyzer);
		Query query = queryParser.parse(queryString);
		Filter filter = null;
		int n = 10000;
		/**
		 * 查询方法为IndexSearcher.search(Query, Filter, int);
		 * Query,查询对象,把用户输入的查询字符串封装成Lucene能够识别的Query。
		 * Filter,用来过虑搜索结果。
		 * 第三个参数(int类型),最多返回的Document的数量。
		 * 返回的是一个TopDocs类型的对象,调用TopDocs.scoreDocs得到查询结果。
		 */
		TopDocs topDocs = indexSearcher.search(query, filter, n); // 搜索
		
		
		

		System.out.println("共有【" + topDocs.totalHits + "】条匹配结果"); // 匹配的结果的数量
		for( ScoreDoc scoreDoc : topDocs.scoreDocs ){
			int docSn = scoreDoc.doc; // 文档的内部编号
			Document doc = indexSearcher.doc(docSn); // 通过编号取出文档
			System.out.println("------------------");
			System.out.println("title   = " + doc.getField("title").stringValue());
			System.out.println("content = " + doc.getField("content").stringValue());
		}
		
		indexSearcher.close();
	}
}

 

 

2  分析lucene的原理

 

 索引文件的保存形式。   索引文件共分为两个部分(索引区和数据区);

 

 

 

索引区 索引区里面存放的均为关键字和什么类型的关键字。并且存放该关键字所对应的数据区内容的标号。(倒序索引)
数据区 数据区中保存的是Document,docuemnt中里面是filed。Filed可以理解为map,里面的数据均为String类型。

 

当开始建立索引时,lucene把内容进行分词,分词产生的关键字存储到索引区中去,并且标注该关键字的类型,如关键字为netease类型为title的索引“netease——title”,其中保存一系列引号去指向数据区中的field。当然这些filed中就是还有该索引的内容。这也就是“倒序索引

当我们进去搜索时,输入关键字后,lucene把我们输入的关键字进行分析,产生了相应的关键字,去到索引区中去查找,如果找到相匹配的信息,就按照索引区中保存的索引号去找到document里面的field,并把这个值返回给view层。

 

3 lucene帮助

 


*** 1,Directory,
有两个:
  a) FSDirectory,将索引放到磁盘中。
  b) RAMDirectory,将索引放到内存中。速度快,但是在jvm退出之后,内存中
的索引就不存在了。可以在jvm退出之前调用另一个使用FSDirectory的
IndexWriter 把内存中的索引转存到文件系统中。
    相应的API为IndexWriter.addIndexesNoOptimize(Directory[]),注意这个调
用代码要放在内存中索引的操作RAMDirectory的IndexWriter关闭后,以便所有的
document都进入RAMDirectory。在创建RAMDirectory的实例时,可以使用无参的构
造方法,或是有一个参数的构造方法:可以指定一个文件路径,以便加载磁盘中的索
引到内存中。


*** 2,相关度排序,
Lucene的搜索结果默认按相关度排序的,所谓相关度,就是文档的得分。Lucene
有一个评分机制,就是对检索结果按某种标准进行评估,然后按分值的高低来对
结果进行排序。

a) 文档的得分与用户输入的关键字有关系,而且是实时运算的结果。得分会受关
键字在文档中出现的位置与次数等的影响。

b) 可以利用Boost影响Lucene查询结果的排序,通过设置Document的Boost来影响
文档的权重,以达到控制查询结果顺序的目的:Document.setBoost(float)。默
认值为1f,值越大,得分越高。

c) 也可以在查询时给Filed指定boost。当同样的term属于不同的field时,如果
field的boost不一样,其所属的文件的得分也不一样。
后面.

*** 3,Analyzer,
分词器,对文本资源进行切分,将文本按规则切分为一个个可以进行索引的最小
单位(关键字)。

对于英文的分词,是按照标点、空白等拆分单词,比较简单;而中文的分词就比
较复杂了,如”中华人民共和国“可以分为”中华”、“人民”、“共和国”,但不应有“华人”
这个词(不符合语义)。

中文分词几种常用的方式:
a) 单字分词,就是按照中文一个字一个字地进行分词。如:我们是中国人,效果:
  我\们\是\中\国\人。(StandardAnalyzer就是这样)。
b) 二分法:按两个字进行切分。如:我们是中国人,效果:我们\们是\是中\中
  国\国人。(CJKAnalyzer就是这样)。
c) 词库分词:按某种算法构造词,然后去匹配已建好的词库集合,如果匹配到就切
  分出来成为词语。通常词库分词被认为是最理想的中文分词算法,如:我们是中
  国人,效果为:我们\中国人。(使用MMAnalyzer)。


*** 4,Highlighter,高亮器,用于高亮显示匹配的关键字。
包含三个主要部分:
1) 格式化器:Formatter(使用SimpleHTMLFormatter,在构造时指定前缀和后缀)。
2) 计分器:Scorer(使用QueryScorer)。
3) 段划分器:Fragmenter(使用SimpleFragmenter,在构造时指定关键字所在的
   内容片段的长度)。

通过方法getBestFragment(Analyzer a, String fieldName,String text)实现高亮。
(如果进行高亮的field中没有出现关键字,返回null)。


* 5,查询,有两种方式:通过Query Parser解析查询字符串或使用API构建查询。
使用Query Parser时不匹分大小写。以下是常用的查询:

1) TermQuery,按Term(关键字)查询(term的值应是最终的关键字,英文应全部小写)。
   TermQuery(Term t);
   syntax: propertyName:keyword;

2) RangeQuery,指定范围查询。
   RangeQuery(Term lowerTerm, Term upperTerm, boolean inclusive);
   syntax: propertyName:[lower TO upper](包含lower和upper);
   syntax: propertyName:{lower TO upper}(不包含lower和upper);

3) PrefixQuery,前缀查询。
   PrefixQuery(Term prefix);
   syntax:propertyName:prefix*;

4) WildcardQuery,通配符查询,可以使用"?"代表一个字符,"*"代表0个或多个字符。
   (通配符不能出现在第一个位置上)
   WildcardQuery(Term term);
   syntax: propertyName:chars*chars?chars

5) MultiFieldQueryParser,在多个Field中查询。
   queryParser = MultiFieldQueryParser(String[] fields, Analyzer analyzer);
   Query query = parse(String query);
  
6) BooleanQuery,布尔查询。这个是一个组合的Query,可以把各种Query添加进
   去并标明他们的逻辑关系。
   TermQuery q1 = new TermQuery(new Term("title","javadoc"));
   TermQuery q2 = new TermQuery(new Term("content","term"));
   BooleanQuery boolQuery = new BooleanQuery();
   boolQuery.add(q1, Occur.MUST);
   boolQuery.add(q2, Occur.MUST_NOT);
  
   Occur.MUST,必须出现。
   Occur.MUST_NOT,必须未出现,不要单独使用。
   Occur.SHOULD,只有一个SHOULD时为必须出现,多于一个时为或的关系。

   syntax: + - AND NOT OR (必须为大写)。

 

 

1
0
分享到:
评论
1 楼 hanwesley 2010-10-15  
谢谢,我在你的基础之上学习的。感觉还不错。

相关推荐

    Lucene初级教程.doc

    标题为“Lucene初级教程.doc”,我们可以推断这是一份关于Lucene的入门级文档,Lucene是Apache软件基金会的一个开放源代码项目,它是一个全文搜索引擎库,广泛应用于Java开发中,用于实现高效、可扩展的信息检索服务...

    Apache_Solr_初级教程

    ### Apache Solr 初级...通过以上知识点的学习,读者应该能够理解 Apache Solr 的基本概念、安装配置流程以及如何使用 Java API 进行文档的添加和查询操作,同时也能掌握中文分词的基本原理及其在 Solr 中的应用方法。

    大数据第一次作业1

    在大数据领域,Nutch是一个广泛使用的...理解Nutch的数据结构和工作原理对于优化爬虫性能、提高搜索引擎质量至关重要。在实际应用中,可能需要根据具体需求调整Nutch的配置,如爬行策略、索引参数等,以达到最佳效果。

    搜索引擎样例

    "搜索引擎样例"是一个专为初级使用者设计的学习项目,旨在帮助他们理解和掌握搜索引擎的基本原理和实现方式。在这个压缩包文件中,包含了一个名为"LuceneTest"的文件,这很可能是基于Apache Lucene库的一个示例程序...

    Java软件开发工程师简历.pdf

    此外,该工程师还熟悉 Lucene,了解搜索引擎的运行原理,Hibernate 中的二级缓存存储原理,并能使用 Hibernate Search3.4.2+二级缓存来优化 SQL 查询。 关系型数据库 该工程师熟悉 MySQL、Oracle 等关系型数据库,...

    Java个人简历模板4.doc

    6. **大数据技术**:掌握Hadoop集群搭建和配置,能够进行大数据分析,理解HDFS和MapReduce的设计原理,熟悉Hive、HBase、Sqoop和Zookeeper等Hadoop周边框架,了解Pig、Flume和Storm。 7. **其他技术**: - JBPM:...

    Java个人简历模板31.doc

    - **Java编程**:求职者精通Java初级和高级知识,包括反射、泛型和代理技术,掌握了面向对象编程思想,并熟悉多种Java设计模式。 - **Java Web开发**:熟悉JSP、Servlet、Filter、Listener、Cookie、Session、EL...

    Java个人简历模板32.doc

    17. **大数据处理**:熟悉Hadoop生态系统,能够部署和配置Hadoop分布式数据集群,理解HDFS和MapReduce工作原理,具备初步的Hadoop应用开发能力。 以上所述,展示了应聘者在Java领域的广泛知识和实践经验,对于寻找...

    PHP开发经理职位描述与岗位职责任职要求.docx

    * 熟识制造工艺流程相关学问,含自动组装工艺,操作员掌握之工艺,机器掌握,过程量具,工艺测试,与零件之制作功能和工艺流程,理解防错防误技巧与概念,理解精益原理 * 电脑技巧,含 MSWord,Excel,AutoCAD 此外,...

    JAVA上百实例源码以及开源项目源代码

    简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!...

Global site tag (gtag.js) - Google Analytics