《Lucene_分析与应用》学习笔记

合集下载

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学习

lucene学习1.基本概念信息检索(IR)是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。

文档:用于搜索的内容部件。

词汇单元:即分词。

词干提取器,如Snowball。

搜索质量主要由查准率(Preciion)和查全率(Recall)来衡量。

[1]P13语法检查器:Lucene的contrib目录提供了两个模块完成此功能。

查询对象:Lucene提供了一个称之为查询解析器(QueryParer),用它可以根据通用查询语法将用户输入的文本处理成查询对象。

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

搜索查询组件涵盖了搜索引擎内部复杂的工作机制,Lucene正是如此,它为你完成这一切。

倒排索引:invertedinde某常见的搜索理论模型有如下3种。

■纯布尔模型(PureBooleanmodel)文档不管是否匹配查询请求,都不会被评分.在该模型下,匹配文档与评分不相关,也是无序的;一条查询仅获取所有匹配文档集合的一个子集。

■向量空间模型(Vectorpacemodel)查询语句和文档都是高维空间的向量模型,这里每一个独立的项都是一个维度。

查询语句和文档之间的相关性或相似性由各自向量之间的距离计算得到.■概率模型(Probabiliticmodel)在该模型中,采用全概率方法来计算文档和查询语句的匹配概率。

Lucene在实现上采用向量空间模型和纯布尔模型,并能针对具体搜索让你决定采用哪种模型。

最后,Lucene返回的文档结果必须用比较经济的方式展现给用户。

搜索范围:涉及分布式搜索,ApacheLucene项目下的Solr和Nutch 项目提供了对索引拆分和复制的支持,另Katta和Elaticearch。

1.1Lucene核心类概貌执行简单的索引过程需要用到以下几个类:■Inde某Writer■Directory■Analyzer■Document■FieldInde某Writer(写索引)是索引过程的核心组件。

lucene学习笔记 1

lucene学习笔记 1
如果要删除删除index中的记录,使用IndexReader类完成, IndexReader会先标记删除,真实的删除行为在indexReader关闭时执行.也就是说IndexReader也会修改index
通过indexReader.undeleteAll()方法只能恢复同一个indexreader实例标记删除的记录
Analyzer 文件的分析器(听起来别扭,还是叫Analyzer好了)的抽象,这个类用来处理分词(对中文尤其重要,转换大小写(Computer->computer,实现查询大小写无关),转换词根(computers->computer),消除stop words等,还负责把其他格式文档转换为纯文本等
没有update方法,要更新记录, 只能通过delete以后再add来进行, 如果要批量进行, 一次性delete完毕以后关闭Reader再打开Writer来add的效率较高
posted on 2005-07-17 11:57 tech.cap 阅读(1108) 评论(0) 编辑 收藏 引用 收藏至365Key 所属分类: java
java搜索引擎: lucene学习笔记 1
简介
Doug Cutting 于2000年开始的项目 2001年9月后加入apache, Lucene是Doug Cutting的middle name 。 目前Lucene已经是apache的top level的项目, 已经不在jakarta下面, 同时也有了python,perl,c++,.net, Ruby(进行中)多个版本
Field.UnStored(String,String) Y Y 大段文本内容,会用来检索,但是检索后不需要从index中取内容,可以根据url去load真实的内容

一步一步跟我学习lucene(1...

一步一步跟我学习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基础学习

搜索引擎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 来做的。

Lucene查询语法详解

Lucene查询语法详解

Lucene查询语法详解Lucene查询Lucene查询语法以可读的⽅式书写,然后使⽤JavaCC进⾏词法转换,转换成机器可识别的查询。

下⾯着重介绍下Lucene⽀持的查询:Terms词语查询词语搜索,⽀持单词和语句。

单词,例如:"test","hello"语句,例如:"hello,world!"多个词语可以通过操作符,连接成更复杂的搜索逻辑。

Field字段查询Lucene⽀持针对某个字段进⾏搜索,语法如:title:hello或者title:"hello title"搜索语句时需要加上双引号,否则:title:hello title就意味着,搜索title为hello,或者包含title关键字的⽂档Term Modifier修饰符查询Lucene⽀持对词语增加修饰,从⽽扩⼤查询的范围。

WildCard Searches通配符查询⽀持在单个单词或者语句中添加通配符:?匹配单个字符*匹配0个或多个字符例如:=>想要搜索test或者textte?t=>想要搜索test tests testertest*⽂档中不⽀持通配符放在搜索的开头,如*test,但是在kibana中是⽀持这种搜索语法的。

Fuzzy Searches模糊词查询⽀持搜索模糊词,如果想要搜索模糊词,需要在词语后⾯加上符号~例如:=>想要搜索和test相近的词test~可以搜索出text或者tests等词也⽀持在~后⾯添加模糊系数,模糊系数[0-1],越靠近1表⽰越相近,默认模糊系数为0.5。

test~0.8Proximity Searches邻近词查询前⾯的模糊词只是针对某个单词,在语句间也存在模糊搜索的概念,只不过不是单词的模糊,⽽是单词之间内容的模糊。

注意要使⽤双引号`""`包围例如:=>想要搜索包含"hello""world"的⽂档,这两个单词中间可以有⼀部分内容(这部分内容通过字符个数限制)"hello world"~10可以匹配"hello 123 world"或者"hello,Tom,world"Range Searches范围查询⽀持范围搜索,可以指定最⼩值和最⼤值,会⾃动查找在这之间的⽂档。

一步一步跟我学习lucene(1...

一步一步跟我学习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_入门整理

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. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

《Lucene 分析与应用》学习笔记一、搜索引擎与Lucene(1)搜索引擎:网络全文搜索引擎(baidu,google,live),目录搜索引擎(yahoo)和元搜索引擎。

(2)Lucene 并不是一个完整的全文检索应用,但却是一个可靠性高、易于扩展的全文检索工具包,可以嵌入到各种应用中,为应用提供全文检索功能。

(3)Lucene 具有突出的优点:①自定义的索引文件格式使得Lucene很容易嵌入到应用系统中,并部署在不同的平台上。

②使用MDA(模型驱动架构)规则设计,使得Lucene易于扩展。

(4)其它搜索引擎开发包①MG4J②WebLucene③Woogle(5)Lucene 的系统架构<1>标引过程IndexWriter ①创建Lucene索引writer.setUseCompoundFile(false);②非复合式索引模式writer.setMergeFactor(2);③设置合并频率为2Document ④建立Document对象document.add(newField);⑤索引文件内容writer.addDocumnet(document);⑥将Document对象加到索引中writer.close();⑦关闭索引,完成索引建立过程说明:②使用复合式索引的优点是可以减少文件的IO操作。

(即设为true或默认情况)③内存中的segments数量达到指定数量时(默认为10)会将其合并为一个Segments。

⑦执行关闭索引的close()方法时,真正完成了将索引文件写入磁盘的操作。

.fdt包含各个域数据(field的特性)信息。

.fdx它是指向.fdt文件的指针。

填写的是.fdt文件中每个文档的域数据信息的起始位置。

.fnm各个域的名字信息。

(6)查询IndexSearch①打开索引queryParser.parse(keyword);②对KeyWord解析searcher.search(query)③检索索引(7)Lucene采用的索引结构对比全文扫描、签名文件、后缀树等索引结构,Lucene为提供准确快速的查询,采用倒排文件作为它的索引结构。

(8)Lucene 体系结构Lucene共分5个模块:语料库、解析、索引、存储、搜索。

①解析模块为搜索模块和索引模块提供了相同的解析过程。

Lucene建立索引过程中,需要对被索引的文件进行分析,对于搜索过程而言,用户输入的查询条件,也需要通过解析。

通过相同的解析过程后,用户的查询信息才能与从文本解析出出的信息相匹配,才能返回给用户正确的结果。

②Index模块提供2种访问协议。

一种为搜索提供访问,另一种协议为维护索引提供服务。

(更新索引信息、优化索引)二、文档逻辑视图与文本分析(1)document(文档),field(域),term(项)将document理解为记录,将field理解为字段,在数据库中,字段有多种类型,所以Lucene中的field也具有一些特定的类型。

Field(String,String,Store.Yes,Index.UN-TOKENZED)存储,不索引,不切词(如:日期、路径)存储,索引,切词(如:标题)不存储,索引,切词(如:内容)注:要按照某个字段来删除某个文档时必须将这个字段设置为索引,否则只是存储就不可以依据此字段来删除文档了。

(2)空格解析器(whitespace Analyzer)(3)标准解析器(StandAnalyzer)标准分析器依靠标准分析器(StandardTokenizer)将输入的文本解析为token流。

解析器特有属性和方法为:属性:停用词表方法:tokenStream方法停用词是一些高频率出现的英文单词但信息量小,会带来索引文件增大,影响查询效率。

解析器过滤规则为:▪标准过滤standFilter()▪转换为小写字符lowercaseFilter()▪去除高频词StopFilter标准分词器(StandTokenizer)(4)在Lucene 的Sandbox包里,能找到CJKAnalyzer,一个中文分词器(二元分词器)如何才能够切分出符合语义的词来呢?①词库法:需要一个相当丰富的词库②词元法:将单词按照n元语法。

CJKAnalyzer就是采用词元法(n=2)实现的解析器。

(5)构造自己的解析器对CJKAnalyzer分析:一个标准的Lucene解析器,需要继承Analyzer2外,常常由以下3部分组成:STOP_WORDS,构造函数,tokenStream方法。

三、Lucene创建索引之一(段索引方式与倒排索引结构)(1)Lucene选用了段索引(SegmentIndex)方式与倒排索引(Inverted Index)结构来完成标引(Indexing)过程,其中段索引方式是一种增量产生索引的方式。

(2)正排是文档指向单词,倒排是单词指向文档。

Word1→doc1,doc2,doc3..Word2→doc1,doc2….倒排索引建立索引的过程中,需要考虑索引更新这一值得研究的问题。

内存中保存的索引与磁盘中保存的索引,二者结构是否相同?在Lucene中采用段索引的生成方式,合并阈值(MergeFactor)影响着内存与硬盘中索引文件的个数。

每添加一个document将生成单一段索引被内存持有,当单一段索引的个数超过合并阈值时,就会通过merge(合并)的过程将单一段索引合并为段索引。

段索引超过合并阈值时就会触发合并过程,合并为一个索引。

注:单一段索引,段索引,索引文件格式是相同的,二者只是规模不同。

Doc→单一段索引Doc→单一段索引】合并→段索引Doc→单一段索引】合并→段索引】合并或优化→索引增量索引过程writer.setMergeFactor(n);设置合并阈值索引写入过程概述:Lucene 的索引文件是按照前面所介绍的3个层面保存了document,field,term的信息。

四、Lucene创建索引之二(在内存中创建索引)(1)Lucene创建索引分两步:内存中创建索引与合并索引到磁盘中。

在IndexWriter的addDocument方法中调用了buildSingleDocSegment方法,每添加一个document,就在内存中创建一个段索引。

(2)每添加一个document,Lucene就认为是创建一个segment索引,通常这个索引保存在内存中,当内存中的索引超过合并阈值或标引过程结束时,都要将索引合并到磁盘中。

(3)当内存中保存的document的索引数超过minMergeDocs阈值,就会调用flushRamSegments方法将内存中的索引保存到磁盘中。

还有其它过程也会调用到这个方法:IndexWriter的close,flush,optimize,常选择close 或optimize方法而引发合并的过程。

索引概念说明:Document类的属性有两个:vector类来存储field,float类型保存boost数值。

PostingTable保存了term的document内频率信息(某个document包含这个term的个数),位置信息与term自身的信息。

.tvf:保存field中term、频率、位置与偏移信息。

因此,Lucene从既能满足一定词汇量规模,又能达到定位效率最优的双重需求出发,采用二层文件结构构建字典文件。

建立document的倒排,需要知道如下信息:①某个term对应的document的编号②term的频率信息。

tf:某个document中包含该term的个数docFreq:文集中包含该term的document个数。

再深入考虑一下,term的频率信息已经隐含在term的位置信息中,term在document 中出现几次(如果出现一次即保存一次位置的信息,就是该term在这个document中出现的频率,如果把位置信息中document编号相同的归为一组,就可以计算出组数,这就是docFreq的值(多少个document包含这个term的数量))所以document的倒排过程,可以认为是记录term位置信息的过程。

在内存中创建过程:①写入field名字文件(.fnm文件)②写入field信息文件(.fdt,.fdx)FieldWriter是field信息文件的写入操作类,该类会创建写入两个文件,.fdt保存了field数据文件,.fdx是.fdt文件的索引。

.fdx文件保存了指向.fdt文件写入信息的起始位置指针。

③写入频率与位置文件(.frg与.prx文件)④TermVector方式写入索引(.tvf,.tvd,.tvx文件)在field中以TermVector方式保存的posting信息需要TermVectorsWriter类来写入,.tvx是.tvd的索引文件,保存了指针信息,指针指向.tvd的document数据位置。

.tvd保存有document(这个document采用TermVector方式保存field)信息,同时它包含一个指针表,表内的指针指向.tvf文件中的field信息。

.tvf保存field中term、频率、位置与偏移信息。

⑤字典文件(.tis与.tii文件)Lucene的字典文件由term信息组成,是一个二层文件结构。

Term信息的排序是有序的(按照字典顺序对field名字与term文本进行两趟排序),查询过程是对这个有序文件逐term,逐字符比对的过程,对原有序term信息添加一个附加索引(快表)就可以快速定位。

所以Lucene在term信息文件(.tis文件)的基础上创建了快表文件(.tii文件)。

Lucene对.tis文件中term个数计数,每到一个分组跨度,便把分组点term信息保存到.tii文件中。

在查询前搜索引擎预热过程中,快表文件便会加载到内存中来快速定位term。

.tii文件分组点term 分组点term.tis文件term term term term term term term term term五、Lucene创建索引之三(索引合并过程)Field文件,字典文件,频率文件,位置文件Segment index →合并前准备(.fnm文件,.fdt文件,.fdx文件,.tis文件,.tii文件,.frq 文件,.prx文件)→合并field文件①→合并posting文件②→posting队列②(.tis文件,.tii 文件,.frq文件,.prx文件)①→是否是indexed→hash(.fnm文件,.fdt文件,.fdx文件)②②→重写合并后的postings文件合并流程简单示意图5.2field与term的合并过程创建索引过程中都是围绕document,field,term来做的。

相关文档
最新文档