第十六讲-Lucene高级进阶续一
- 格式:pptx
- 大小:105.33 KB
- 文档页数:4
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⼊门+实现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 使⽤于搜索的⼀个基本单元。
目录1.1全文检索引擎Lucene相关技术及应用(第1部分) (2)1.1.1站内搜索相关技术介绍 (2)1.1.2Apache Lucene全文检索引擎工具包 (3)1.1.3Lucene系统库及应用 (9)1.1.4索引管理相关的代码示例 (33)1.1全文检索引擎Lucene相关技术及应用(第1部分)1.1.1站内搜索相关技术介绍1、站内搜索的必要性在以往的网站建设,企业系统的搭建过程中,因为信息比较简单和信息的数量也比较少,站内搜索可能不是必要的功能。
而如今,信息量的增大,网站逻辑的复杂,企业自身对信息架构、管理、发布的需求,以及用户对信息的组织、查询、可寻性的要求越来越高,于是站内搜索的功能要求出现了。
而如果在Web应用系统中能够提供站内搜索,则能够很快的得到用户所要检索的信息,这样给用户提供了很大的方便。
2、和通用搜索引擎的区别谷歌、百度、搜搜等通用搜索引擎都会免费开放站内搜索功能,以嵌入网页代码的形式保持与搜索引擎机器人的沟通、爬取。
但采用此方法的主要弊病有如下三种:(1)这些通用搜索引擎不能及时、全部抓取网站最新页面内容。
这对电子商务网站信息(如价格、活动有效时间等)经常更新的特点来说是致命的,用户查到的可能是过时信息。
(2)既然是所谓通用引擎,其对搜索结果的展示也是通用的,没有差异性的。
其不能按照商城自身业务逻辑去做排序、过滤、展示是其最大的弱项。
(3)通用搜索,无法提供热词,搜索推荐词,关联词等功能,还需要二次开发,增加工作量和复杂度。
因此,站内搜索的出现也是有其具体原因和需求的,在搜索的精确度和效果上击败了通用搜索引擎。
1.1.2Apache Lucene全文检索引擎工具包1、Lucene(/)Lucene是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。
Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎——索引、分词、搜索三个主要的部分。
标题:探讨Lucene对比中文近义词用法1. 简介为了更好地理解Lucene对比中文近义词用法,我们首先需要了解Lucene的基本概念和中文近义词的特点。
Lucene是一个全文检索引擎库,它提供了丰富的API,可以用于构建强大的全文搜索功能。
而中文近义词则是指在中文语境中,表达相似意义的词语,这些词语在不同的语境中可能会有微小的差别,但整体的意思是相通的。
2. Lucene的基本原理和功能Lucene通过倒排索引的方式来快速定位文档中的关键词,从而实现全文搜索的功能。
它采用了分词器来处理文本,将文本分割成若干个独立的单词,并将这些单词进行索引。
在搜索时,用户输入的查询语句也经过相同的分词处理,再与索引进行匹配,最终返回相关的文档。
3. 中文近义词的特点在中文语境中,由于词语的复杂性和多义性,往往会存在大量的近义词。
这些近义词可能在不同的场景中有不同的使用方式,但它们的基本意思是一致的。
“喜欢”和“爱好”就是一对中文近义词,它们都表示喜爱或偏好的意思,只是在语感上有细微的区别。
4. Lucene对比中文近义词用法在使用Lucene进行搜索时,对于中文近义词的处理往往是一个挑战。
由于中文的特殊性,同一个词可能存在多种不同的表达方式,而传统的搜索引擎很难将它们准确地匹配在一起。
针对这一问题,Lucene提供了同义词扩展的功能,可以将一些近义词视作同一个词来处理。
这样一来,用户在搜索时无需考虑到所有的近义词,只需要输入其中一个,就能够搜索到相关的文档。
5. 个人观点和总结通过对Lucene对比中文近义词用法的探讨,我们可以发现,Lucene在处理中文近义词时的确存在一些挑战,但它也提供了相应的解决方案。
在实际应用中,我们可以根据具体的需求,合理地进行同义词扩展,以提升搜索结果的准确性和覆盖范围。
对于中文近义词的掌握也需要结合具体的语境和语气来理解,不能简单地进行机械替换。
Lucene对比中文近义词用法的探讨,有助于我们更好地理解和应用这一强大的全文搜索引擎库。
Lucene教程详解Lucene-3.0.0配置一、Lucene开发环境配置step1.Lucene开发包下载step2.Java开发环境配置step3.Tomcat安装step4.Lucene开发环境配置解压下载的lucene-3.0.0.zip,可以看到lucene-core-3.0.0.jar和lucene-demos-3.0.0.jar这两个文件,将其解压(建议放在安装jdk的lib文件夹内),并把路径添加到环境变量的classpath。
二、Lucene开发包中Demo调试控制台应用程序step1.建立索引>java org.apache.lucene.demo.IndexFiles [C:\Java](已经存在的任意文件路径)将对C:\Java下所有文件建立索引,同时,在当前命令行位置将生成“index”文件夹。
step2.执行查询>java org.apache.lucene.demo.SearchFiles将会出现“Query:”提示符,在其后输入关键字,回车,即可得到查询结果。
Web应用程序step1.将lucene-core-3.0.0.jar和lucene-demos-3.0.0jar这两个文件复制到安装Tomcat 的\common\lib中step2.解压下载的lucene-3.0.0.zip,可以看到luceneweb.war文件。
将该文件复制到安装Tomcat的\webappsstep3.重启Tomcat服务器。
step4.建立索引>java org.apache.lucene.demo.IndexHTML -create -index [索引数据存放路径] [被索引文件路径](如:D:\lucene\temp\index D:\lucene\temp\docs)step5.打开安装Tomcat的\webapps\luceneweb\configuration.jsp文件,找到String indexLocation = "***",将"***"改为第四步中[索引数据存放路径],保存关闭。
lucene全文检索精华lucene全文检索1 概念全文检索(Full-Text Retrieval)是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置。
当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程.1.1 lucene全文检索的特性全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。
全面、准确和快速是衡量全文检索系统的关键指标。
关于全文检索的特性,我们要知道:1,只处理文本。
2,不处理语义。
3,搜索时英文不区分大小写。
4,结果列表有相关度排序。
下图就是显示“1+1等于几”这个搜索要求对应的结果。
可以看到,是没有“2”这个结果的,结果页面都是出现了这些词的网页 .1.2 全文检索的应用场景我们使用Lucene,主要是做站内搜索,即对一个系统内的资源进行搜索。
如BBS、BLOG中的文章搜索,网上商店中的商品搜索等。
使用Lucene的项目有Eclipse、Jira等。
一般不做互联网中资源的搜索,因为不易获取与管理海量资源(专业搜索方向的公司除外)。
2 第一个lunece程序2.1 准备lucene的开发环境搭建Lucene的开发环境只需要加入Lucene的Jar包,要加入的jar包至少要有: ? lucene-core-4.4.0.jar(核心包)? analysis\\common\\lucene-analyzers-common-4.4.0.jar(分词器) ?highlighter\\lucene-highlighter-4.4.0.jar(高亮) ? \\memory\\lucene-memory-4.4.0.jar(高亮)? queryparser\\ lucene-queryparser-4.4.0.jar (查询解析)2.2 实现建立索引功能(IndexWriter)/*** 使用indexWriter对数据库建立索引.. * @throws IOException */ @Test public void createIndex() throws IOException{//索引存放的位置...Directory directory=FSDirectory.open(new File(\));//lucene当前使用的匹配版本Version matchVersion=Version.LUCENE_44;//分词器,对文本进行分词,抽象类,由子类实现不同的分词方式Analyzer analyzer=new StandardAnalyzer(matchVersion); //索引写入的配置 IndexWriterConfig indexWriterConfig=new//构建用于操作索引的类IndexWriter indexWriter=new IndexWriter(directory,IndexWriterConfig(matchVersion, analyzer);indexWriterConfig);//索引库里面的要遵守一定的结构,(索引结构...) 在索引库当中保存的都是documentDocument doc=new Document(); //索引document里面页游很多的字段... /** * 1:字段的名称 * 2:字段对应的值* 3:该字段在索引库中是否存储 */IndexableField id=new IntField(\, 1, Store.YES);//StringField不会根据分词器去拆分,只有后面的String全包括才能被搜索到IndexableField title=new StringField(\, \培训,传智播客//TextField如果按照默认分词器去拆分,中文则是按照单个中文拆分的专注Java培训10年\, Store.YES);IndexableField content=new TextField(\, \培训的龙头老大,口碑最好的java培训机构,进来看看同学们的呐喊\, Store.YES);doc.add(id);}doc.add(title); doc.add(content);indexWriter.addDocument(doc);indexWriter.close();2.3 实现搜索功能(IndexSearcher)/*** 使用indexSearcher对数据进行搜索 * @throws IOException */ @Testpublic void queryIndex() throws IOException{//索引存放的位置Directory directory=FSDirectory.open(new File(\)); //创建索引读取器IndexReader indexReader=DirectoryReader.open(directory);//通过indexSearcher去检索索引目录...IndexSearcher indexSearcher=new IndexSearcher(indexReader);//我们以后只要根据索引查找,整个过程肯定要分2次..//这是一个搜索条件..,通过定义条件来进行查找...(可以拿到编号,编号都放在了//term 我需要根据哪个字段进行检索,字段对应的值...//Query是抽象类,由子类去实现不同的查询规则Query query=new TermQuery(new Term(\, \));//搜索先搜索索引目录(第一次搜)..不会直接搜索到document(第二次搜) //找到符合query条件的前面N条记录...如果不加条件则会全部查询出来ScoreDoc数组中,遍历数组就获得了编号)TopDocs topDocs=indexSearcher.search(query, 10); System.out.println(\总记录数是:\+topDocs.totalHits);//返回结果的数组(得分文档)ScoreDoc[] scoreDocs=topDocs.scoreDocs; //返回一个击中..for(ScoreDoc scoreDoc:scoreDocs){int docID=scoreDoc.doc; //根据编号去击中对应的文档//lucene的索引库里有很多document,lucene为每个document定义一个编号,唯一标识(docId),是自增长的。
中国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内部是没有提供这种增量索引的实现的;这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建。
对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况,这势必严重影响用户的体验;比较常见的增量索引的实现是:•设置一个定时器,定时从数据源中读取比现有索引文件中新的内容或是数据源中带有更新标示的数据。
•对数据转换成需要的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使用与优化2008-01-23 20:581lucene 简介1.1什么是luceneLucene是一个全文搜索框架,而不是应用产品。
因此它并不像或者google Desktop那么拿来就能用,它只是提供了一种工具让你能实现这些产品。
1.2 lucene能做什么要回答这个问题,先要了解lucene的本质。
实际上lucene的功能很单一,说到底,就是你给它若干个字符串,然后它为你提供一个全文搜索服务,告诉你你要搜索的关键词出现在哪里。
知道了这个本质,你就可以发挥想象做任何符合这个条件的事情了。
你可以把站内新闻都索引了,做个资料库;你可以把一个数据库表的若干个字段索引起来,那就不用再担心因为“紐ike%”而锁表了;你也可以写个自己的搜索引擎……1.3你该不该选择lucene下面给岀一些测试数据,如果你觉得可以接受,那么可以选择。
测试一:250万记录,300M左右文本,生成索引380M左右,800线程下平均处理时间300ms o测试二:37000记录,索引数据库中的两个varchar字段,索引文件2. 6M, 800 线程下平均处理时间1.5ms。
2lucene的工作方式lucene提供的服务实际包含两部分:一入一出。
所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。
2.1写入流程源字符串首先经过analyzer处理,包括:分词,分成一个个单词;去除stopword (非索引字)(可选)。
将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。
将索引写入存储器,存储器可以是内存或磁盘。
2.2读出流程用户提供搜索关键词,经过analyzer处理。
对处理后的关键词搜索索引找岀对应的Documento用户根据需要从找到的Document中提取需要的Field。
对于Lucene的索引过程,除了将词(Term)写入倒排表并最终写入Lucene的索引文件外,还包括分词(Analyzer)和合并段(merge segments)的过程,本次不包括这两部分,将在以后的文章中进行分析。
Lucene的索引过程,很多的博客,文章都有介绍,推荐大家上网搜一篇文章:《Annotated Lucene》,好像中文名称叫《Lucene源码剖析》是很不错的。
想要真正了解Lucene索引文件过程,最好的办法是跟进代码调试,对着文章看代码,这样不但能够最详细准确的掌握索引过程(描述都是有偏差的,而代码是不会骗你的),而且还能够学习Lucene的一些优秀的实现,能够在以后的工作中为我所用,毕竟Lucene是比较优秀的开源项目之一。
由于Lucene已经升级到3.0.0了,本索引过程为Lucene 3.0.0的索引过程。
一、索引过程体系结构Lucene 3.0的搜索要经历一个十分复杂的过程,各种信息分散在不同的对象中分析,处理,写入,为了支持多线程,每个线程都创建了一系列类似结构的对象集,为了提高效率,要复用一些对象集,这使得索引过程更加复杂。
其实索引过程,就是经历下图中所示的索引链的过程,索引链中的每个节点,负责索引文档的不同部分的信息,当经历完所有的索引链的时候,文档就处理完毕了。
最初的索引链,我们称之基本索引链。
为了支持多线程,使得多个线程能够并发处理文档,因而每个线程都要建立自己的索引链体系,使得每个线程能够独立工作,在基本索引链基础上建立起来的每个线程独立的索引链体系,我们称之线程索引链。
线程索引链的每个节点是由基本索引链中的相应的节点调用函数addThreads创建的。
为了提高效率,考虑到对相同域的处理有相似的过程,应用的缓存也大致相当,因而不必每个线程在处理每一篇文档的时候都重新创建一系列对象,而是复用这些对象。
所以对每个域也建立了自己的索引链体系,我们称之域索引链。
域索引链的每个节点是由线程索引链中的相应的节点调用addFields 创建的。
Lucene学习笔记(一)申明:此文章中说到的分词器就是分析器中的一种,不要理解错了。
注意:以下内容中有没有解释留待以后章节解释的有:1. writer.optimize();对索引进行优化一、Lucene基础:大纲: 1. 信息获取与搜索引擎的发展2. Lucene的历史3. 建立索引(索引库)与搜索1. 信息获取技术包含:信息的表示、存储、组织和对信息的访问方法。
信息的表示和组织是为了用户更容易的访问到需要的信息。
1.1 一般来说,信息获取的流程分为以下四步:1.1.1 获取信息之前,要构建文本数据库,即将来需要进行检索的数据(被检索的数据)1.1.2 需要建立文档的索引,通过文档索引可以检索到对应的文本数据库中对应的数据;有很多建立文档索引的方法,但是用的最多的还是"倒排索引技术",其中Lucene就是采用的这种建立文档索引的技术1.1.3 完成文档索引的建立之后就可以进行检索了,此时需要用户提供一个查询关键字,该关键字将被分析然后利用一些文本处理技术进行处理,当然也可以根据具体的需求进行一系列的处理。
1.1.4 查询关键字准备好之后,进入查询,根据查询关键字可以与文档索引中的数据得到匹配进而得到文本数据库中与匹配上的文档索引对应的数据,然后反馈给用户,当然反馈之前我们可以进行排序等处理,让最接近用户需求的信息排在最前面显示2. 搜索引擎:分为"全文搜索引擎(FullT ext Search Engine)"和"分类目录(Directory)"2.1 全文搜索引擎:通过一个叫网络机器人(Spider)或者叫网络蜘蛛(Crawlers)的软件,自动分析网络上的各种连接并且获取网页信息内容而且会按照规则加以分析整理,记入数据库。
优缺点:使用关键字和一定的语法;全文搜索引擎因为依靠网络机器人等收集数据,所以数据库的容量非常庞大,但是它的查询往往不准确。
Lucene基本使用介绍今天用了下Lucene,发现网上虽然也有不少介绍它的文档,不过很多都偏向介绍概念呀、设计或者是一些更为深入的东西,对于其入门使用的介绍性的文档并不多,就写了这么一篇。
Lucene基本使用介绍本文的目的不在于对Lucene的概念和设计这些进行介绍,仅在于介绍怎么样去使用Lucene来达到自己想要的几种常见的全文检索的需求,如果想深入了解Lucene的话本文不会带给你什么收获的。
看完本文后想更深入的了解Lucene请访问:一.概述随着系统信息的越来越多,怎么样从这些信息海洋中捞起自己想要的那一根针就变得非常重要了,全文检索是通常用于解决此类问题的方案,而Lucene 则为实现全文检索的工具,任何应用都可通过嵌入它来实现全文检索。
二.环境搭建从上下载最新版本的lucene.jar,将此jar作为项目的build path,那么在项目中就可以直接使用lucene了。
三.使用说明3.1.基本概念这里介绍的主要为在使用中经常碰到一些概念,以大家都比较熟悉的数据库来进行类比的讲解,使用Lucene进行全文检索的过程有点类似数据库的这个过程,table---→查询相应的字段或查询条件----→返回相应的记录,首先是IndexWriter,通过它建立相应的索引表,相当于数据库中的table,在构建此索引表时需指定的为该索引表采用何种方式进行构建,也就是说对于其中的记录的字段以什么方式来进行格式的划分,这个在Lucene中称为Analyzer,Lucene提供了几种环境下使用的Analyzer:SimpleAnalyzer、StandardAnalyzer、GermanAnalyzer等,其中StandardAnalyzer是经常使用的,因为它提供了对于中文的支持,在表建好后我们就需要往里面插入用于索引的记录,在Lucene中这个称为Document,有点类似数据库中table的一行记录,记录中的字段的添加方法,在Lucene中称为Field,这个和数据库中基本一样,对于Field Lucene分为可被索引的,可切分的,不可被切分的,不可被索引的几种组合类型,通过这几个元素基本上就可以建立起索引了。
Lucene 是基于Java 的全文信息检索包,它目前是Apache Jakarta 家族下面的一个开源项目。
在这篇文章中,我们首先来看如何利用Lucene 实现高级搜索功能,然后学习如何利用Lucene 来创建一个健壮的Web 搜索应用程序。
在本篇文章中,你会学习到如何利用Lucene 实现高级搜索功能以及如何利用Lucene 来创建Web 搜索应用程序。
通过这些学习,你就可以利用Lucene 来创建自己的搜索应用程序。
架构概览通常一个Web 搜索引擎的架构分为前端和后端两部分,就像图一中所示。
在前端流程中,用户在搜索引擎提供的界面中输入要搜索的关键词,这里提到的用户界面一般是一个带有输入框的Web 页面,然后应用程序将搜索的关键词解析成搜索引擎可以理解的形式,并在索引文件上进行搜索操作。
在排序后,搜索引擎返回搜索结果给用户。
在后端流程中,网络爬虫或者机器人从因特网上获取Web 页面,然后索引子系统解析这些Web 页面并存入索引文件中。
如果你想利用Lucene 来创建一个Web 搜索应用程序,那么它的架构也和上面所描述的类似,就如图一中所示。
Figure 1. Web 搜索引擎架构利用Lucene 实现高级搜索Lucene 支持多种形式的高级搜索,我们在这一部分中会进行探讨,然后我会使用Lucene 的API 来演示如何实现这些高级搜索功能。
布尔操作符大多数的搜索引擎都会提供布尔操作符让用户可以组合查询,典型的布尔操作符有AND, OR, NOT。
Lucene 支持 5 种布尔操作符,分别是AND, OR, NOT, 加(+), 减(-)。
接下来我会讲述每个操作符的用法。
•OR: 如果你要搜索含有字符A 或者B 的文档,那么就需要使用OR 操作符。
需要记住的是,如果你只是简单的用空格将两个关键词分割开,其实在搜索的时候搜索引擎会自动在两个关键词之间加上OR 操作符。
例如,“Java OR Lucene” 和“Java Lucene” 都是搜索含有Java 或者含有Lucene 的文档。
Grafana是一个开源的数据可视化工具,可以帮助用户更直观地查看和理解数据。
而Lucene是一个基于Java的全文搜索引擎库,用于实现全文搜索。
在Grafana中,使用Lucene语法可以帮助用户进行更精确和高效的数据查询和过滤。
本文将介绍Grafana中Lucene语法的基本规则和常用语法,帮助用户更好地利用Lucene语法进行数据查询和分析。
一、Lucene语法的基本规则1. 字段查询在Lucene中,可以使用字段查询来指定搜索的字段,例如"title:Grafana"表示在标题字段中搜索包含Grafana的数据。
2. 通配符查询Lucene支持通配符查询,可以使用*代表0或多个任意字符,使用?代表一个任意字符。
3. 逻辑运算可以使用逻辑运算符AND、OR、NOT来组合多个查询条件,例如"title:Grafana AND author:Lucene"表示同时满足标题包含Grafana 并且作者是Lucene的数据。
4. 范围查询使用[]表示闭区间,{}表示开区间,例如"date:[xxx TO xxx}"表示在2019年内的数据。
5. 模糊查询可以使用~后接一个整数来表示模糊查询的最大编辑距离,例如"Graf~"表示匹配Graf、Graff等单词。
6. 短语查询使用双引号来表示短语查询,例如""Grafana Lucene""表示搜索包含Grafana和Lucene相连的短语。
二、Grafana中Lucene语法的常用语法1. 查询表达式在Grafana的查询表达式中,可以使用Lucene语法来指定查询条件,例如"title:Grafana AND author:Lucene"。
2. 聚合查询可以使用Lucene语法来进行聚合查询,例如"status:200"表示查询状态码为200的数据。
Lucene⾼级搜索⾃定义评分public class MyScoreQuery {public void searchByScoreQuery(){try {IndexSearcher searcher=new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory())); Query q=new TermQuery(new Term("content","java"));//创建⼀个评分FieldScoreQuery fd=new FieldScoreQuery("score",Type.INT);//2 根据评分域和原有的Query创建⾃定义的Query对象MyCustomScoreQuery query=new MyCustomScoreQuery(q,fd);TopDocs tds=null;tds=searcher.search(query, 100);SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:ss");for(ScoreDoc sd:tds.scoreDocs){Document d=searcher.doc(sd.doc);System.out.println(sd.doc+"("+sd.score+")"+"["+d.get("filename")+"【"+d.get("path")+"】--->"+d.get("score")+"--->"+d.get("size")+" "+sdf.format(new Date(Long.valueOf(d.get("date"))))+"]");}searcher.close();} catch (NumberFormatException e) {e.printStackTrace();} catch (CorruptIndexException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}public void searchByFileScoreQuery(){try {IndexSearcher searcher=new IndexSearcher(IndexReader.open(FileIndexUtils.getDirectory())); Query q=new TermQuery(new Term("content","java"));FilenameScoreQuery query=new FilenameScoreQuery(q);TopDocs tds=null;tds=searcher.search(query, 100);SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:ss");for(ScoreDoc sd:tds.scoreDocs){Document d=searcher.doc(sd.doc);System.out.println(sd.doc+"("+sd.score+")"+"["+d.get("filename")+"【"+d.get("path")+"】--->"+d.get("score")+"--->"+d.get("size")+" "+sdf.format(new Date(Long.valueOf(d.get("date"))))+"]");}searcher.close();} catch (NumberFormatException e) {e.printStackTrace();} catch (CorruptIndexException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}private class DateScoreProvider extends CustomScoreProvider{long[] dates=null;public DateScoreProvider(IndexReader reader) {super(reader);//通过域缓存获取⽂件名try {dates=FieldCache.DEFAULT.getLongs(reader, "date");} catch (IOException e) {e.printStackTrace();}}@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {//如何个格局doc的名称获取相应的field的值/** 在reader在没有关闭之前,所有的数据会存储在⼀个域缓存中,可以通过域缓存获取很多有⽤的信息 */long date=dates[doc];long today=new Date().getTime();long year=1000*60*60*24*365;//表⽰的是这⼀年之内的if(today-date<=year){//为其加分}return subQueryScore/1.5f;}}@SuppressWarnings("serial")private class FilenameScoreQuery extends CustomScoreQuery{public FilenameScoreQuery(Query subQuery) {super(subQuery);}@Overrideprotected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException {return new FilenameScoreProvider(reader);}}private class FilenameScoreProvider extends CustomScoreProvider{String[] filenames=null;public FilenameScoreProvider(IndexReader reader) {super(reader);//通过域缓存获取⽂件名try {filenames=FieldCache.DEFAULT.getStrings(reader, "filename");} catch (IOException e) {e.printStackTrace();}}@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {//如何个格局doc的名称获取相应的field的值/** 在reader在没有关闭之前,所有的数据会存储在⼀个域缓存中,可以通过域缓存获取很多有⽤的信息*/String filename=filenames[doc];System.out.println(filename);if(filename.endsWith("注解")|| filename .endsWith(".ini")){return subQueryScore*1.5f;}return subQueryScore/1.5f;}}private class MyCustomScoreQuery extends CustomScoreQuery{public MyCustomScoreQuery(Query subQuery, ValueSourceQuery valSrcQuery) {super(subQuery, valSrcQuery);}@Overrideprotected CustomScoreProvider getCustomScoreProvider(IndexReader reader) throws IOException { //默认情况实现的评分是通过原有的评分传⼊进来的评分域所获取的评分来确定最终打分//为了根据不同的需求进⾏评分,需要⾃⼰进⾏评分设定/*** ⾃定评分的步骤* 创建⼀个类继承于CustomScoreProvider* 覆盖customScore⽅法*/return new MyCustomScoreProvider(reader);}}private class MyCustomScoreProvider extends CustomScoreProvider{public MyCustomScoreProvider(IndexReader reader) {super(reader);// TODO Auto-generated constructor stub}/*** subQueryScore 表⽰默认⽂档的打分* valScrScore 表⽰的评分域的打分*/@Overridepublic float customScore(int doc, float subQueryScore, float valSrcScore) throws IOException {// TODO Auto-generated method stubreturn subQueryScore/valSrcScore;}}}View Code⾃定义Queryparserpublic class CustomParser extends QueryParser {public CustomParser(Version matchVersion, String f, Analyzer a) {super(matchVersion, f, a);}@Overrideprotected org.apache.lucene.search.Query getFuzzyQuery(String field, String termStr, float minSimilarity)throws ParseException {throw new ParseException("由于性能原因,已经禁⽤了模糊查询,请输⼊更精确的信息进⾏查询");}@Overrideprotected org.apache.lucene.search.Query getWildcardQuery(String field, String termStr) throws ParseException { throw new ParseException("由于性能原因,已经禁⽤了通配符查询,请输⼊更精确的信息进⾏查询");}@Overrideprotected org.apache.lucene.search.Query getRangeQuery(String field, String arg1, String arg2, boolean arg3)throws ParseException {//if(field.equals("size")){return NumericRangeQuery.newIntRange(field, Integer.parseInt(arg1), Integer.parseInt(arg2), arg3, arg3);}else if(field.equals("date")){//格式化⽇期String dateType="yyyy-MM-dd";Pattern pattern = pile("\\d{4}-\\d{2}-\\d{2}");if(pattern.matcher(arg1).matches() && pattern.matcher(arg2).matches()){SimpleDateFormat sdf=new SimpleDateFormat(dateType);try {long start=sdf.parse(arg1).getTime();long end=sdf.parse(arg2).getTime();return NumericRangeQuery.newLongRange(field, start, end, arg3, arg3);} catch (java.text.ParseException e) {e.printStackTrace();}}}return new TermRangeQuery(field,arg1,arg2,arg3,arg3);}}View Code。
lucene创建索引原理lucene是一个开源的全文搜索引擎库,被广泛应用于信息检索领域。
它以其高效的索引和查询能力而闻名,成为许多搜索引擎和文本分析工具的基础。
本文将介绍lucene的创建索引原理,从索引的创建到查询的过程,帮助读者了解lucene的工作原理。
我们需要了解什么是索引。
在信息检索中,索引是指将大量文档转化为一种数据结构,以便于快速查找和检索。
索引可以理解为一本书的目录,它记录了每个词在哪些文档中出现。
lucene的索引是基于倒排索引的,即以词为单位记录文档的位置信息。
lucene的索引创建过程可以分为以下几个步骤。
首先,需要将文档分析成词项,即将文本按照一定的规则切分为单词。
这一步骤被称为分词(Tokenization),它可以将文本中的字符序列转化为一系列词项(term)。
lucene提供了丰富的分词器,用于支持不同语言和需求的文本分析。
接下来,需要对词项进行标准化处理,以便于建立更精确的索引。
标准化处理包括词干提取(Stemming)和词项归一化(Normalization)。
词干提取是将词项转化为其词干或原型形式,以消除词形变化的影响。
词项归一化是将不同形式的词项映射为同一个标准形式,以避免重复建立索引。
然后,需要将处理后的词项存储到索引中。
lucene使用倒排索引(Inverted Index)结构来存储词项和文档之间的映射关系。
倒排索引由多个倒排列表(Inverted List)组成,每个倒排列表存储了一个词项在哪些文档中出现。
倒排列表包含了词项在文档中的位置信息,以及其他统计信息,如词频(term frequency)和文档频率(document frequency)等。
为了提高查询效率,lucene对倒排索引进行了优化。
它使用了多级索引(Multi-level Indexing)的结构,将索引划分为多个段(Segment),每个段包含了一部分文档和对应的倒排列表。
每个段都有自己的索引和倒排列表,查询时可以只搜索相关的段,而不需要扫描整个索引。