lucene基础学习
lucene笔记-视频配套笔记

lucene笔记-视频配套笔记传智播客 Java学院传智.入云龙全文检索技术之Lucene1 课程计划1、什么全文检索数据类型:结构化数据和非结构化数据非结构化数据查询方法全文检索的概念2、什么是Lucene3、Lucene实现全文检索的流程(重点)4、Lucene的入门程序(重点)5、分析器Analyzer(重点)7、索引库的维护(重点)i. 索引库的增加索引ii. 删除索引iii. 修改索引8、索引库的查询(重点)i. 使用Query的子类查询ii. 使用QueryParser查询8、相关的排序2 什么全文检索结构化数据:数据的长度类型是固定的。
数据库中的数据非结构化数据:长度不固定格式不固定。
Word文档、excel、pdf、txt。
2.1 结构化数据的查询使用sql语句查询就可以2.2 非结构化数据的查询需求:在文件中找出包含java字符的文档。
传智播客 Java学院传智.入云龙2.2.1 实现方法1、目测2、顺序扫描。
如果文件量大的话比如说20G,顺序扫描会变的很慢。
3、非结构化的数据变结构化先从文件中找出文件所有的词汇,形成一个列表。
查询的时候直接查询列表,找到关键词后根据这词找到相应的文档。
一次创建多次使用。
2.3 全文检索的概念这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。
2.4 全文检索应用领域1、搜索引擎,百度、谷歌2、站内搜索a) 微博搜索b) 论坛搜索3、电商搜索,搜索的是商品信息。
3 什么是Lucene3.1 Lucene的概念Lucene是apache下的一个开放源代码的全文检索引擎工具包。
提供了完整的查询引擎和索引引擎,部分文本分析引擎。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能。
3.2 Lucene和搜索引擎的区别Lucene是一个工具包:需要进行编程才能实现全文检索的功能呢搜索引擎:一套独立运行的系统,提供了全文检索功能。
Lucene初级教程

Lucene初级教程2007-12-26 15:24 点击次数:0 次1 lucene简介1.1 什么是luceneLucene是一个全文搜索框架,而不是应用产品。
因此它并不像 或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。
2 lucene的工作方式lucene提供的服务实际包含两部分:一入一出。
所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。
2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword(可选)。
将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。
将索引写入存储器,存储器可以是内存或磁盘。
2.2读出流程用户提供搜索关键词,经过analyzer处理。
对处理后的关键词搜索索引找出对应的Document。
用户根据需要从找到的Document中提取需要的Field。
3 一些需要知道的概念3.1 analyzerAnalyzer是分析器,它的作用是把一个字符串按某种规则划分成一个个词语,并去除其中的无效词语,这里说的无效词语是指英文中的“of”、“the”,中文中的“的”、“地”等词语,这些词语在文章中大量出现,但是本身不包含什么关键信息,去掉有利于缩小索引文件、提高效率、提高命中率。
分词的规则千变万化,但目的只有一个:按语义划分。
这点在英文中比较容易实现,因为英文本身就是以单词为单位的,已经用空格分开;而中文则必须以某种方法将连成一片的句子划分成一个个词语。
具体划分方法下面再详细介绍,这里只需了解分析器的概念即可。
3.2 document用户提供的源是一条条记录,它们可以是文本文件、字符串或者数据库表的一条记录等等。
一条记录经过索引之后,就是以一个Document的形式存储在索引文件中的。
Lucene入门+实现

Lucene⼊门+实现Lucene简介详情见:()lucene实现原理其实⽹上很多资料表明了,lucene底层实现原理就是倒排索引(invertedindex)。
那么究竟什么是倒排索引呢?经过Lucene分词之后,它会维护⼀个类似于“词条--⽂档ID”的对应关系,当我们进⾏搜索某个词条的时候,就会得到相应的⽂档ID。
不同于传统的顺排索引根据⼀个词,知道有哪⼏篇⽂章有这个词。
图解:Lucene在搜索前⾃⾏⽣成倒排索引,相⽐数据库中like的模糊搜索效率更⾼!Lucene 核⼼API索引过程中的核⼼类1. Document⽂档:他是承载数据的实体(他可以集合信息域Field),是⼀个抽象的概念,⼀条记录经过索引之后,就是以⼀个Document的形式存储在索引⽂件中的。
2. Field:Field 索引中的每⼀个Document对象都包含⼀个或者多个不同的域(Field),域是由域名(name)和域值(value)对组成,每⼀个域都包含⼀段相应的数据信息。
3. IndexWriter:索引过程的核⼼组件。
这个类⽤于创建⼀个新的索引并且把⽂档加到已有的索引中去,也就是写⼊操作。
4. Directroy:是索引的存放位置,是个抽象类。
具体的⼦类提供特定的存储索引的地址。
(FSDirectory 将索引存放在指定的磁盘中,RAMDirectory ·将索引存放在内存中。
)5. Analyzer:分词器,在⽂本被索引之前,需要经过分词器处理,他负责从将被索引的⽂档中提取词汇单元,并剔除剩下的⽆⽤信息(停⽌词汇),分词器⼗分关键,因为不同的分词器,解析相同的⽂档结果会有很⼤的不同。
Analyzer是⼀个抽象类,是所有分词器的基类。
搜索过程中的核⼼类1. IndexSearcher :IndexSearcher 调⽤它的search⽅法,⽤于搜索IndexWriter 所创建的索引。
2. Term :Term 使⽤于搜索的⼀个基本单元。
一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...自定义排序说明我们在做lucene搜索的时候,可能会需要排序功能,虽然lucene 内置了多种类型的排序,但是如果在需要先进行某些值的运算然后在排序的时候就有点显得无能为力了;要做自定义查询,我们就要研究lucene已经实现的排序功能,lucene的所有排序都是要继承FieldComparator,然后重写内部实现,这里以IntComparator为例子来查看其实现;IntComparator相关实现其类的声明为public static class IntComparator extends NumericComparator<Integer>,这里说明IntComparator接收的是Integer类型的参数,即只处理IntField的排序;IntComparator声明的参数为:[java] view plain copy1.private final int[] values;2.private int bottom; // Value of bottom of queue3.private int topValue;查看copy方法可知•values随着类初始化而初始化其长度•values用于存储NumericDocValues中读取到的内容具体实现如下:values的初始化[java] view plain copy1./**2.* Creates a new comparator based on {@link Integer#co mpare} for {@code numHits}.3.* When a document has no value for the field, {@code mi ssingValue} is substituted.4.*/5.public IntComparator(int numHits, String field, Integer mi ssingValue) {6.super(field, missingValue);7.values = new int[numHits];8.}values值填充(此为IntComparator的处理方式)[java] view plain copy1.@Override2.public void copy(int slot, int doc) {3.int v2 = (int) currentReaderValues.get(doc);4.// Test for v2 == 0 to save Bits.get method call for5.// the common case (doc has value and value is non-zero):6.if (docsWithField != null && v2 == 0 && !docsWithField. get(doc)) {7.v2 = missingValue;8.}9.10.values[slot] = v2;11.}这些实现都是类似的,我们的应用实现自定义排序的时候需要做的是对binaryDocValues或NumericDocValues的值进行计算,然后实现FieldComparator内部方法,对应IntComparator就是如上的值copy操作;然后我们需要实现compareTop、compareBottom和compare,IntComparator的实现为:[java] view plain copy1.@Override2.public int compare(int slot1, int slot2) {3.return pare(values[slot1], values[slot2]);4.}5.6.@Override7.public int compareBottom(int doc) {8.int v2 = (int) currentReaderValues.get(doc);9.// Test for v2 == 0 to save Bits.get method call for10.// the common case (doc has value and value is non-zero):11.if (docsWithField != null && v2 == 0 && !docsWithFi eld.get(doc)) {12.v2 = missingValue;13.}14.15.return pare(bottom, v2);16.}[java] view plain copy1.@Override2.public int compareTop(int doc) {3.int docValue = (int) currentReaderValues.get(doc);4.// Test for docValue == 0 to save Bits.get method call for5.// the common case (doc has value and value is non-zero):6.if (docsWithField != null && docValue == 0 && !docsWit hField.get(doc)) {7.docValue = missingValue;8.}9.return pare(topValue, docValue);10.}实现自己的FieldComparator要实现FieldComparator,需要对接收参数进行处理,定义处理值的集合,同时定义BinaryDocValues和接收的参数等,这里我写了一个通用的比较器,代码如下:[java] view plain copy1.package com.lucene.search;2.3.import java.io.IOException;4.5.import org.apache.lucene.index.BinaryDocValues;6.import org.apache.lucene.index.DocValues;7.import org.apache.lucene.index.LeafReaderContext;8.import org.apache.lucene.search.SimpleFieldComparator;9.10.import com.lucene.util.ObjectUtil;11.12./**自定义comparator13.* @author lenovo14.*15.*/16.public class SelfDefineComparator extends SimpleFie ldComparator<String> {17.private Object[] values;//定义的Object[],同IntComparator18.private Object bottom;19.private Object top;20.private String field;21.private BinaryDocValues binaryDocValues;//接收的BinaryDocValues,同IntComparator中的NumericDocValues22.private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类23.private Object[] params;//接收的参数24.25.public SelfDefineComparator(String field, int numHits, Object[] params,ObjectUtil objectUtil) {26.values = new Object[numHits];27.this.objectUtil = objectUtil;28.this.field = field;29.this.params = params;30.}31.32.@Override33.public void setBottom(int slot) {34.this.bottom = values[slot];35.}36.37.@Override38.public int compareBottom(int doc) throws IOExcepti on {39.Object distance = getValues(doc);40.return (bottom.toString()).compareTo(distance.toStrin g());41.}42.43.@Override44.public int compareTop(int doc) throws IOException {45.Object distance = getValues(doc);46.return pareTo(top,distance);47.}48.49.@Override50.public void copy(int slot, int doc) throws IOException {51.values[slot] = getValues(doc);52.}53.54./**��ȡdocID��Ӧ��value55.* @param doc56.* @return57.*/58.private Object getValues(int doc) {59.Object instance = objectUtil.getValues(doc,params,bin aryDocValues) ;60.return instance;61.}62.63.@Override64.protected void doSetNextReader(LeafReaderContext context)65.throws IOException {66.binaryDocValues = DocValues.getBinary(context.reade r(), field);//context.reader().getBinaryDocValues(field);67.}68.69.@Override70.public int compare(int slot1, int slot2) {71.return pareTo(values[slot1],values[slot2]);72.}73.@Override74.public void setTopValue(String value) {75.this.top = value;76.}77.78.@Override79.public String value(int slot) {80.return values[slot].toString();81.}82.83.}其中ObjectUtil是一个接口,定义了值处理的过程,最终是要服务于comparator的compare方法的,同时对comparator的内部compare方法进行了定义ObjectUtil接口定义如下:[java] view plain copy1.package com.lucene.util;2.3.import org.apache.lucene.index.BinaryDocValues;4.5.public interface ObjectUtil {6.7./**自定义的获取处理值的方法8.* @param doc9.* @param params10.* @param binaryDocValues11.* @return12.*/13.public abstract Object getValues(int doc, Object[] par ams, BinaryDocValues binaryDocValues) ;14.15./**compare比较器实现16.* @param object17.* @param object218.* @return19.*/20.public abstract int compareTo(Object object, Object object2);21.22.}我们不仅要提供比较器和comparator,同时还要提供接收用户输入的FiledComparatorSource[java] view plain copy1.package com.lucene.search;2.3.import java.io.IOException;4.5.import org.apache.lucene.search.FieldComparator;6.import org.apache.lucene.search.FieldComparatorSource;7.8.import com.lucene.util.ObjectUtil;9.10./**comparator用于接收用户原始输入,继承自FieldComparatorSource实现了自定义comparator的构建11.* @author lenovo12.*13.*/14.public class SelfDefineComparatorSource extends Fie ldComparatorSource {15.private Object[] params;//接收的参数16.private ObjectUtil objectUtil;//这里为了便于拓展用接口代替抽象类17.18.public Object[] getParams() {19.return params;20.}21.22.public void setParams(Object[] params) {23.this.params = params;24.}25.26.public ObjectUtil getObjectUtil() {27.return objectUtil;28.}29.30.public void setObjectUtil(ObjectUtil objectUtil) {31.this.objectUtil = objectUtil;32.}33.34.public SelfDefineComparatorSource(Object[] params, ObjectUtil objectUtil) {35.super();36.this.params = params;37.this.objectUtil = objectUtil;38.}39.40.@Override41.public FieldComparator<?> newComparator(String fie ldname, int numHits,42.int sortPos, boolean reversed) throws IOException {43.//实际比较由SelfDefineComparator实现44.return new SelfDefineComparator(fieldname, numHit s, params, objectUtil);45.}46.}相关测试程序,这里我们模拟一个StringComparator,对String 值进行排序[java] view plain copy1.package com.lucene.search;2.3.import org.apache.lucene.analysis.Analyzer;4.import org.apache.lucene.analysis.standard.StandardAnal yzer;5.import org.apache.lucene.document.BinaryDocValuesFiel d;6.import org.apache.lucene.document.Document;7.import org.apache.lucene.document.Field;8.import org.apache.lucene.document.StringField;9.import org.apache.lucene.index.DirectoryReader;10.import org.apache.lucene.index.IndexReader;11.import org.apache.lucene.index.IndexWriter;12.import org.apache.lucene.index.IndexWriterConfig;13.import org.apache.lucene.index.IndexWriterConfig.Op enMode;14.import org.apache.lucene.index.Term;15.import org.apache.lucene.search.IndexSearcher;16.import org.apache.lucene.search.MatchAllDocsQuery;17.import org.apache.lucene.search.Query;18.import org.apache.lucene.search.ScoreDoc;19.import org.apache.lucene.search.Sort;20.import org.apache.lucene.search.SortField;21.import org.apache.lucene.search.TermQuery;22.import org.apache.lucene.search.TopDocs;23.import org.apache.lucene.search.TopFieldDocs;24.import org.apache.lucene.store.RAMDirectory;25.import org.apache.lucene.util.BytesRef;26.27.import com.lucene.util.CustomerUtil;28.import com.lucene.util.ObjectUtil;29.import com.lucene.util.StringComparaUtil;30.31./**32.*33.* @author 吴莹桂34.*35.*/36.public class SortTest {37.public static void main(String[] args) throws Exceptio n {38.RAMDirectory directory = new RAMDirectory();39.Analyzer analyzer = new StandardAnalyzer();40.IndexWriterConfig indexWriterConfig = new IndexWri terConfig(analyzer);41.indexWriterConfig.setOpenMode(OpenMode.CREATE_ OR_APPEND);42.IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);43.addDocument(indexWriter, "B");44.addDocument(indexWriter, "D");45.addDocument(indexWriter, "A");46.addDocument(indexWriter, "E");mit();48.indexWriter.close();49.IndexReader reader = DirectoryReader.open(directory) ;50.IndexSearcher searcher = new IndexSearcher(reader);51.Query query = new MatchAllDocsQuery();52.ObjectUtil util = new StringComparaUtil();53.Sort sort = new Sort(new SortField("name",new SelfD efineComparatorSource(new Object[]{},util),true));54.TopDocs topDocs = searcher.search(query, Integer.MA X_VALUE, sort);55.ScoreDoc[] docs = topDocs.scoreDocs;56.for(ScoreDoc doc : docs){57.Document document = searcher.doc(doc.doc);58.System.out.println(document.get("name"));59.}60.}61.62.private static void addDocument(IndexWriter writer,S tring name) throws Exception{63.Document document = new Document();64.document.add(new StringField("name",name,Field.Sto re.YES));65.document.add(new BinaryDocValuesField("name", new BytesRef(name.getBytes())));66.writer.addDocument(document);67.}68.}其对应的ObjectUtil实现如下:[java] view plain copy1.package com.lucene.util;2.3.import org.apache.lucene.index.BinaryDocValues;4.import org.apache.lucene.util.BytesRef;5.6.public class StringComparaUtil implements ObjectUtil {7.8.@Override9.public Object getValues(int doc, Object[] params,10.BinaryDocValues binaryDocValues) {11.BytesRef bytesRef = binaryDocValues.get(doc);12.String value = bytesRef.utf8T oString();13.return value;14.}15.16.@Override17.public int compareTo(Object object, Object object2) {18.// TODO Auto-generated method stub19.return object.toString().compareTo(object2.toString());20.}21.22.}。
Lucene搜索入门教程

Lucene搜索入门教程1.了解搜索技术1.1搜索引擎搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。
搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。
搜索引擎的原理可以看到搜索引擎的功能主要是三部分:●爬行和抓取数据(爬虫多用python来编写、但是java也能实现)●对数据对预处理(提取文字、中文分词、建立倒排索引)提供搜索功能(用户输入关键词后、去索引库搜索数据)在上述三个步骤中,java要解决的往往是后两个步骤:数据处理和搜索。
那么,我们之前学习的mysql知识也能实现数据的存储和搜索,为什么还要学新的东西呢?1.2传统数据库搜索的问题要实现类似百度的复杂搜索,或者京东的商品搜索,如果使用传统的数据库存储数据,那么会存在一系列的问题:●数据库数据单表存储能力有限,无法存储海量数据●解决大数据,可以进行分库分表。
但是分库分表会增加业务复杂度●搜索只能通过模糊匹配,效率极低●模糊搜索可能导致全表扫描,效率非常差在这里,比较棘手的其实是第二个问题:查询效率低,类似百度和京东这样的网站,对性能要求极高。
如果用户点击搜索需要很久才能拿到数据,没人愿意一直等待下去。
那么问题来了:如何才能提高模糊搜索时的效率呢?答案是:倒排索引技术1.3什么是倒排索引倒排索引是一种存储数据的方式,与传统查找有很大区别:●传统查找:采用数据按行存储,查找时逐行扫描,或者根据索引查找,然后匹配搜索条件,效率较差.概括来讲是先找到文档,然后看是否匹配.传统线性查找一个10MB的word文件,查找关键字如果在文档最后,大约3秒钟●倒排索引:首先对文档数据按照id进行索引存储,然后对文档中的数据分词,记录对词条进行索引,并记录词条在文档中出现的位置。
这样查找时只要找到了词条,就找到了对应的文档。
Lucene入门与使用

中国Lucene入门与使用本文主要面向具体使用,适用于已熟悉java编程的lucene初学者。
1. Lucene的简介1.1 Lucene 历史org.apache.lucene包是纯java语言的全文索引检索工具包。
Lucene的作者是资深的全文索引/检索专家,最开始发布在他本人的主页上,2001年10月贡献给APACHE,成为APACHE基金jakarta的一个子项目。
目前,lucene广泛用于全文索引/检索的项目中。
lucene也被翻译成C#版本,目前发展为(不过最近好象有流产的消息)。
1.2 Lucene 原理lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。
在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行匹配查询。
因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的xml或者大数据的字符类型。
2.Lucene的下载和配置2.1 Lucene的下载lucene在jakarta项目中的发布主页:/lucene/docs/index.html。
以下主要针对windows 用户,其它用户请在上面的地址中查找相关下载。
lucene的.jar包的下载(包括.jar和一个范例demo):/jakarta/lucene/binaries/lucene-1.4-fina l.ziplucene的源代码下载:/mirrors/apache/jakarta/lucene/source/lucene-1 .4-final-src.ziplucene的api地址:/lucene/docs/api/index.html本文使用lucene版本:lucene-1.4-final.jar。
一步一步跟我学习lucene(1...

一步一步跟我学习lucene(1...这两天加班,不能兼顾博客的更新,请大家见谅。
有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引。
对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的;这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建。
对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况,这势必严重影响用户的体验;比较常见的增量索引的实现是:•设置一个定时器,定时从数据源中读取比现有索引文件中新的内容或是数据源中带有更新标示的数据。
•对数据转换成需要的document并进行索引这样做较以上的那种全删除索引然后重建的好处在于:•数据源查询扫描的数据量小•相应的更新索引的条数也少,减少了大量的IndexWriter的commit和close这些耗时操作以上解决了增量的问题,但是实时性的问题还是存在的:•索引的变更只有在IndexWriter的commit执行之后才可以体现出来那么我们怎样对实时性有个提升呢,大家都知道lucene索引可以以文件索引和内存索引两种方式存在,相较于文件索引,内存索引的执行效率要高于文件索引的构建,因为文件索引是要频繁的IO操作的;结合以上的考虑,我们采用文件索引+内存索引的形式来进行lucene 的增量更新;其实现机制如下:•定时任务扫描数据源的变更•对获得的数据源列表放在内存中•内存中的document达到数量限制的时候,以队列的方式删除内存中的索引,并将之添加到文件索引•查询的时候采用文件+内存索引联合查询的方式以达到NRT效果定时任务调度器java内置了TimerT ask,此类是可以提供定时任务的,但是有一点就是TimerTask的任务是无状态的,我们还需要对任务进行并行的设置;了解到quartz任务调度框架提供了有状态的任务StatefulJob,即在本次调度任务没有执行完毕时,下次任务不会执行;常见的我们启动一个quartz任务的方式如下:[java] view plain copy1.Date runTime = DateBuilder.evenSecondDate(new Date()) ;2.StdSchedulerFactory sf = new StdSchedulerFactory();3.Scheduler scheduler = sf.getScheduler();4.JobDetail job = JobBuilder.newJob(XXX.class).build();5.Trigger trigger = TriggerBuilder.newTrigger().startAt(runTi me).withSchedule(SimpleScheduleBuilder.simpleSchedule().withI ntervalInSeconds(3).repeatForever()).forJob(job).build();6.scheduler.scheduleJob(job, trigger);7.8.scheduler.start();</span>以上我们是设置了每三秒执行一次定时任务,而任务类是XXX 任务类通用方法这里我定义了一个XXX的父类,其定义如下:[java] view plain copy1.package com.chechong.lucene.indexcreasement;2.3.import java.util.List;4.import java.util.TimerTask;5.6.import org.apache.lucene.store.RAMDirectory;7.import org.quartz.Job;8.import org.quartz.StatefulJob;9.10./**有状态的任务:串行执行,即不允许上次执行没有完成即开始本次如果需要并行给接口改为Job即可11.* @author lenovo12.*13.*/14.public abstract class BaseInCreasementIndex implem ents StatefulJob {15./**16.* 内存索引17.*/18.private RAMDirectory ramDirectory;19.public BaseInCreasementIndex() {20.}21.public BaseInCreasementIndex(RAMDirectory ramDire ctory) {22.super();23.this.ramDirectory = ramDirectory;24.}25.26./**更新索引27.* @throws Exception28.*/29.public abstract void updateIndexData() throws Excep tion;30./**消费数据31.* @param list32.*/33.public abstract void consume(List list) throws Excepti on;34.}任务类相关实现,以下方法是获取待添加索引的数据源XXXInCreasementIndex[java] view plain copy1.@Override2.public void execute(JobExecutionContext context) throw s JobExecutionException {3.try {4.XXXInCreasementIndex index = new XXXInCreasementIn dex(Constants.XXX_INDEX_PATH, XXXDao.getInstance(), RamDir ectoryControl.getRAMDireactory());5.index.updateIndexData();6.} catch (Exception e) {7.// TODO Auto-generated catch block8.e.printStackTrace();9.}10.}[java] view plain copy1.@Override2.public void updateIndexData() throws Exception {3.int maxBeanID = SearchUtil.getLastIndexBeanID();4.System.out.println(maxBeanID);5.List<XXX> sources = XXXDao.getListInfoBefore(maxBeanID);、、6.if (sources != null && sources.size() > 0) {7.this.consume(sources);8.}9.}这里,XXX代表我们要获取数据的实体类对象consume方法主要是做两件事:•数据存放到内存索引•判断内存索引数量,超出限制的话以队列方式取出超出的数量,并将之存放到文件索引[java] view plain copy1.@Override2.public void consume(List list) throws Exception {3.IndexWriter writer = RamDirectoryControl.getRAMIndex Writer();4.RamDirectoryControl.consume(writer,list);5.}上边我们将内存索引和队列的实现放在了RamDirectoryControl 中内存索引控制器首先我们对内存索引的IndexWriter进行初始化,在初始化的时候需要注意先执行一次commit,否则会提示no segments的异常[java] view plain copy1.private static IndexWriter ramIndexWriter;2.private static RAMDirectory directory;3.static{4.directory = new RAMDirectory();5.try {6.ramIndexWriter = getRAMIndexWriter();7.} catch (Exception e) {8.// TODO Auto-generated catch block9.e.printStackTrace();10.}11.}12.public static RAMDirectory getRAMDireactory(){13.return directory;14.}15.public static IndexSearcher getIndexSearcher() throw s IOException{16.IndexReader reader = null;17.IndexSearcher searcher = null;18.try {19.reader = DirectoryReader.open(directory);20.} catch (IOException e) {21. e.printStackTrace();22.}23.searcher = new IndexSearcher(reader);24.return searcher;25.}26./**单例模式获取ramIndexWriter27.* @return28.* @throws Exception29.*/30.public static IndexWriter getRAMIndexWriter() throw s Exception{31.if(ramIndexWriter == null){32.synchronized (IndexWriter.class) {33.Analyzer analyzer = new IKAnalyzer();34.IndexWriterConfig iwConfig = new IndexWriterConfig (analyzer);35.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);36.try {37.ramIndexWriter = new IndexWriter(directory, iwConfig);mit();39.ramIndexWriter.close();40.iwConfig = new IndexWriterConfig(analyzer);41.iwConfig.setOpenMode(OpenMode.CREATE_OR_APPE ND);42.ramIndexWriter = new IndexWriter(directory, iwConfig);43.} catch (IOException e) {44.// TODO Auto-generated catch block45. e.printStackTrace();46.}47.}48.}49.50.return ramIndexWriter;51.}定义一个获取内存索引中数据条数的方法[java] view plain copy1./**根据查询器、查询条件、每页数、排序条件进行查询2.* @param query 查询条件3.* @param first 起始值4.* @param max 最大值5.* @param sort 排序条件6.* @return7.*/8.public static TopDocs getScoreDocsByPerPageAndSortFi eld(IndexSearcher searcher,Query query, int first,int max, Sort s ort){9.try {10.if(query == null){11.System.out.println(" Query is null return null ");12.return null;13.}14.TopFieldCollector collector = null;15.if(sort != null){16.collector = TopFieldCollector.create(sort, first+max, fal se, false, false);17.}else{18.SortField[] sortField = new SortField[1];19.sortField[0] = new SortField("createTime",SortField.Ty pe.STRING,true);20.Sort defaultSort = new Sort(sortField);21.collector = TopFieldCollector.create(defaultSort,first+ max, false, false, false);22.}23.searcher.search(query, collector);24.return collector.topDocs(first, max);25.} catch (IOException e) {26.// TODO Auto-generated catch block27.}28.return null;29.}此方法返回结果为T opDocs,我们根据TopDocs的totalHits来获取内存索引中的数据条数,以此来鉴别内存占用,防止内存溢出。
lucene_入门整理

1.概述Lucene是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎。
Lucene以其方便使用、快速实施以及灵活性受到广泛的关注。
它可以方便地嵌入到各种应用中实现针对应用的全文索引、检索功能,本总结使用lucene--2.3.2。
2.lucene 的包结构1、org.apache.lucene.analysis对需要建立索引的文本进行分词、过滤等操作, 语言分析器,主要用于的切词Analyzer是一个抽象类,管理对文本内容的切分词规则。
2、org.apache.lucene.analysis.standard是标准分析器3、org.apache.lucene.document提供对Document和Field的各种操作的支持。
索引存储时的文档结构管理,类似于关系型数据库的表结构。
Document相对于关系型数据库的记录对象,Field主要负责字段的管理。
4、org.apache.lucene.index是最重要的包,用于向Lucene提供建立索引时各种操作的支持。
索引管理,包括索引建立、删除等。
索引包是整个系统核心,全文检索的根本就是为每个切出来的词建索引,查询时就只需要遍历索引,而不需要去正文中遍历,从而极大的提高检索效率。
5、org.apache.lucene.queryParser提供检索时的分析支持。
查询分析器,实现查询关键词间的运算,如与、或、非等。
6、org.apache.lucene.search 负责检索。
检索管理,根据查询条件,检索得到结果。
7、org.apache.lucene.store提供对索引存储的支持。
数据存储管理,主要包括一些底层的I/0操作。
8、org.apache.lucene.util提供一些常用工具类和常量类的支持3.索引文件格式a).fnm格式包含了Document中所有field名称b).fdt与.fdx格式.fdt文件用于存储具有Store.YES属性的Field的数据;.fdx是一个索引,用于存储Document在.fdt中的位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
搜索引擎Lucene第一章Lucene简介Lucene是apache软件基金会jakarta项目组的一个子项目,是一个开放源代码[的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
第二章lucene索引的建立的五个基础类索引的建立,Lucene 提供了五个基础类,分别是Document, Field, IndexWriter, Analyzer, Directory。
以下是他们的用途:DocumentDocument的含义为文档,在Lucene中,它代表一种逻辑文件。
Lucene本身无法对物理文件建立索引,而只能识别并处理Document的类型文件。
Lucene从Document取出相关的数据源并根据属性配置进行相应的处理。
Field对象是用来描述一个文档的某个属性的lucene中的field也具有一些特定的类型如在中,Field内部包含两个静态的内部类分别是Store和Index详细的描述了Field的属性,它们分别表示Field的储存方式和索引方式。
Store类有3个公有的静态属性::表示该Field不需要储存。
:表示该Field需要储存。
:表示使用压缩方式来保存这个Field的值。
Index有4个公有的静态属性::表示该Field不需要索引,也就是用户不需要去查找该Field的值。
:表示该Field先被分词再被索引。
TOKENIZED:表示不对该Field进行分词,但是要对他进行索引,也就是该Field会被用户查找。
:表示对该Field进行索引,但是不使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗。
Analyzer在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由Analyzer 来做的。
Analyzer 类是一个抽象类,它有多个实现。
针对不同的语言和应用需要选择适合的Analyzer。
Analyzer 把分词后的内容交给IndexWriter 来建立索引。
IndexWriterIndexWriter 是Lucene 用来创建索引的一个核心的类,他的作用是把一个个的Document 对象加到索引中来。
Directory这个类代表了Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是FSDirectory,它表示一个存储在文件系统中的索引的位置。
第二个是RAMDirectory,它表示一个存储在内存当中的索引的位置。
建立索引过程的初始化在Lucene中,IndexWrite的主要作用是对索引进行创建,加入Document,合并各种索引段,以及控制与索引相关的各方面,它是Lucene的索引主要操作者。
3个公有的构造函数:要获得一个IndexWrite的实例,就需要从它的构造函数入手尝试。
具体的构造函数如下:public IndexWrite(String path, Analyzer a, Boolean create)public IndexWrite(File path , Analyzer a, Boolean create)public IndexWrite(Directory d, Analyzer a, Boolean create)第一个参数为索引存放路径,第二个参数Analyzer为分词器,第三个参数是一个Boolean 类型的值,这个参数的含义是:在由第一个参数所指定的路径处,删除原目录内的所有内容重新构建索引:或是追加新的Document。
像索引添加文档IndexWrite准备好以后,就可以想索引目录中添加Document。
IndexWrite提供了很简单的接口以供开发人员进行Document的添加:public void addDocument(Document doc)public void addDocument(Document doc,Analyzer analyzer)注意:在使用addDocument方法加入所有的Document后,一定要使用IndexWrite的close方法来关闭索引器,使所有在I/O缓存中的数据都写入到磁盘上,关闭各种流。
这样才能最终完成索引的建立。
如果没有关闭,就会发现索引目录中内除了一个segment 文件外一无所有。
很多初学者在刚开始使用Lucene时经常忘记关闭IndexWrite,这样会导致索引的数据滞留在缓存中,未写入磁盘,有可能连目录的锁也没有去除。
在下次对同一个目录加入索引文件的时候可能会提示目录处于锁定状态而造成无法加入文件。
限制每个Field中词条的数量有必要为Lucene限制每个Field内可以建立索引的词条数。
public void setMaxFieldLength(int maxFieldLength)索引过程的优化合并因子mergeFactor说明:无论是磁盘上创建新segment还是将segment合并,都需要进行磁盘的I/O操作,相对于内存的操作来说,这种磁盘I/O操作是比较费时的。
因此,当mergeFactor取比较小的值时,内存中驻留的文档数量较少,向磁盘写入segment的操作较多,故此时将占用较小的内存,但是索引的建立由于I/O操作频繁所以会比较慢。
而当mergeFactor 取较大值时,内存中驻留的Document数量较多,向磁盘写入segemnt的操作较少,故此时将占用较多的内存,但索引的建立速度会比较快。
maxMergeDocs一个较大的MaxMergeDocs适用于应对大批量的文档索引建立,而增量式的索引则使用较小的MaxMergeDocs。
minMergeDocs当索引将被存到磁盘中时,需要首先保存在内存中,minMergeDocs就是用来限制这个内存中的文档数量的。
索引的合并和优化FSDirectory 与RAMDirectory对于lucene来说这两种目录都可以作为索引的存储路径,FSDirectory指的是在文件系统中的一个路径。
当lucene向其中写入索引时,会直接将索引写到磁盘上,RAMDirectory是内存中的区域,虽然向其中添加document的过程与使用FSDirectory中的内存写入磁盘,当虚拟机退出后,里面的内容也会随之消失。
因此需要将RAMDirectory中的内容转移到FSDirectory中。
代码:从索引中删除文档索引的读取工具IndexReader删除IndexReader 主要负责对索引的各种读取和维护工作,如打开一个索引、取得索引中的某个文档、获取索引中的总文档的数量,甚至从索引中删除某个文档。
生成实例方法IndexReader reader = ( INDEX_STORE_PATH );方法(0);在luncene的内部使用类似回收站的机制来管理Document的删除,在每个Document 被索引中删除时,它只相当于被扔进了回收站,并未实际删除。
既然是回收站,Lucene提供了undeleteAll()方法实现反删除。
真正的实现从一个索引中删除文档需要使用IndexWriter对索引optimize一次,luncene就会重新为每个文档分配ID值,这样那些标记为已删除的Document就真正的被无理删除了。
IndexWriter writer = new IndexWriter( INDEX_STORE_PATH,new StandardAnalyzer(),false );();使用Field信息来删除批量文档IndexReader的deleteDocuments()方法是一个能批量删除索引的方法,它删除索引是按照词条进行的,也就是说,每个词条都可以用其所在的Field和他的值来表示。
Lucene同步法则开发人员容易忽略掉同步问题,一旦发生这种情况,索引的完整性和数据的一致性就遇到了挑战。
出现在想索引中添加文档时或将文档从索引中删除时,会在IndexWrite初始化时创建,然后在调用IndexWriter的close()方法是被释放。
另外,会在Indexreader使用delete方法删除文档时创建,并在调用IndexReader的close()方法是被释放。
主要是与segment合并和读取操作相关,例如,他出现在IndexWriter初始化时,但是一旦当segment的信息被读取完毕,他会立刻被释放。
另外,当调用IndexWriter的addIndexes()或mergeSegments()方法时,都会生成这个锁。
的新类:IndexModifier类IndexModifier,它集成了IndexWriter的大部分功能和IndexReader中对索引的删除功能。
第三章Lucene的搜索Lucene里与搜索相关的API多数被包含在包中。
其中最重要的是IndexSearch类。
在Lucene中,所有与搜索相关的操作都需要用到这个类。
的构造方法public IndexSearch( String path )throws IOExceptionpublic IndexSearch(Directory directory)throws IOExceptionpublic IndexSearch( IndexReader r )最简单的使用代码的多种search方法Must 最终结果Must_not子句的查询结果使用它时,需要实例化一个sort对象,并使用Searcher提供的search( Query,Sort )接口来实现。
的构造方法public Sort();INDEXORDER)按一个或多个Field来排序Sort sort = new Sort();SortField f1 = new SortField( ”bookNumber”,,false );SortField f2 = new SortField( ”publishdate”,,false );( new SortField[]{f1,f2} )Hits hits = ( q,sort )搜索的过滤器搜索时过滤器是一种减少搜索范围的方式,即使搜索结果匹配,但是由于文档已经被过滤,所以仍然不会返回给客户,有了这种特性就可以实现很多功能,比如可以用它来实现一种安全机制,既保护某些文档无法被检索到过滤器的基本结构Public abstract BitSet bits( IndexReader reader )throws IOException;BitSets是一种“位集合”队列,这个队列的每个元素都只有两种取值,即true或false,lucene以这种值来代表文档是否被过滤,也就是说,当lucene返回结果时,会先遍历BitSet,仅将那些对应值为true的文档返回。