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 (必须为大写)。
分享到:
相关推荐
标题为“Lucene初级教程.doc”,我们可以推断这是一份关于Lucene的入门级文档,Lucene是Apache软件基金会的一个开放源代码项目,它是一个全文搜索引擎库,广泛应用于Java开发中,用于实现高效、可扩展的信息检索服务...
### Apache Solr 初级...通过以上知识点的学习,读者应该能够理解 Apache Solr 的基本概念、安装配置流程以及如何使用 Java API 进行文档的添加和查询操作,同时也能掌握中文分词的基本原理及其在 Solr 中的应用方法。
在大数据领域,Nutch是一个广泛使用的...理解Nutch的数据结构和工作原理对于优化爬虫性能、提高搜索引擎质量至关重要。在实际应用中,可能需要根据具体需求调整Nutch的配置,如爬行策略、索引参数等,以达到最佳效果。
"搜索引擎样例"是一个专为初级使用者设计的学习项目,旨在帮助他们理解和掌握搜索引擎的基本原理和实现方式。在这个压缩包文件中,包含了一个名为"LuceneTest"的文件,这很可能是基于Apache Lucene库的一个示例程序...
此外,该工程师还熟悉 Lucene,了解搜索引擎的运行原理,Hibernate 中的二级缓存存储原理,并能使用 Hibernate Search3.4.2+二级缓存来优化 SQL 查询。 关系型数据库 该工程师熟悉 MySQL、Oracle 等关系型数据库,...
6. **大数据技术**:掌握Hadoop集群搭建和配置,能够进行大数据分析,理解HDFS和MapReduce的设计原理,熟悉Hive、HBase、Sqoop和Zookeeper等Hadoop周边框架,了解Pig、Flume和Storm。 7. **其他技术**: - JBPM:...
- **Java编程**:求职者精通Java初级和高级知识,包括反射、泛型和代理技术,掌握了面向对象编程思想,并熟悉多种Java设计模式。 - **Java Web开发**:熟悉JSP、Servlet、Filter、Listener、Cookie、Session、EL...
17. **大数据处理**:熟悉Hadoop生态系统,能够部署和配置Hadoop分布式数据集群,理解HDFS和MapReduce工作原理,具备初步的Hadoop应用开发能力。 以上所述,展示了应聘者在Java领域的广泛知识和实践经验,对于寻找...
* 熟识制造工艺流程相关学问,含自动组装工艺,操作员掌握之工艺,机器掌握,过程量具,工艺测试,与零件之制作功能和工艺流程,理解防错防误技巧与概念,理解精益原理 * 电脑技巧,含 MSWord,Excel,AutoCAD 此外,...
简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!...