- 浏览: 10235 次
- 性别:
- 来自: 厦门
最新评论
lucene各个模块用途
建立索引和检索图解
以一个Demo来查看查询代码粗略逻辑
Document.add()方法流程
这个方法主要功能是将field字段和值保存到缓存中去,等待close()方法调用时写入文件。其中为了增加效率启用了多线程创建索引分词。分词组件可以自己实现只要继承Analyzer类。在分词组件里面重载incrementToken(不大记得好像是)或者自己实现一个类继承Tocken,在类里面重载incrementToken方法。这样,如果索引字段的定义了需要分词的话,就会调用你重载的这个方法,以此实现自定义分词效果。
看了4.9+的代码,这个方法以及被定义为final。作者开发了另一个方法来提供用户重载,实现一样效果。
下面贴一个程序运行的关键代码,以及基于4.7.0实现的一个Analyzer.
writer.close()方法的流程(用画图工具画的,超级烂。下次引以为戒)
关键的一部分代码:
英文单词大小写处理
lucene用他自带的standardAnalyzer在建立索引的时候是区分大小写的。在查询query的时候会通通转成小写,导致查询不到。那么可以复制一份源代码,放到本地改一下。调用本地就可以
参考:
因为lucene虽然版本升级,方法上有很多改变,我感觉用户体验明显好多了。但是目前他整体的架构没看得大改变。所以以前的一些书籍还是可以看得。记录一下文档地址,这是一本很好的书:http://www.open-open.com/doc/view/f92fa668d8b84626abd20a05b6eb014e
建立索引和检索图解
以一个Demo来查看查询代码粗略逻辑
public class TestDemo extends LuceneTestCase { public void testDemo() throws IOException, ParseException { //创建一个分词器使用Whitespace-lowercasing analyzer,且无停用词. Analyzer analyzer = new MockAnalyzer( random); //保存索引到内存: //Directory directory = newDirectory(); //会创建2个文件segements.gen(内容为索引的field字段)/segement_N(内容为空) // 如果要保存到硬盘,用下面替换: Directory directory = FSDirectory. open( new File("D:\\index" )); RandomIndexWriter iwriter = new RandomIndexWriter( random, directory, analyzer); //maxFieldLength 长度溢出将在这里打印 iwriter.w.setInfoStream(VERBOSE ? System. out : null); //新建文档 Document doc = new Document(); //需要索引的值 String text = "This is the text to be indexed."; //建立索引,此时不创建文件放内存,第三个参数设置用来判断是否要分词。 doc.add(newField("fieldname" , text, Field.Store.YES, Field.Index.ANALYZED)); //创建2个文件.fdt.ftx但是没有填充值 iwriter.addDocument(doc); //这里默认commit了,填充了值,合并段,合并文档等,还创建了其他各种文件 iwriter.close(); // 查询索引: IndexReader ireader = IndexReader.open(directory); // read-only=true IndexSearcher isearcher = new IndexSearcher(ireader); //创建个默认查询,文字:"text": QueryParser parser = new QueryParser( TEST_VERSION_CURRENT, "fieldname", analyzer); Query query = parser.parse("text"); TopDocs hits = isearcher.search(query, null, 1); // 循环结果集: for (int i = 0; i < hits. scoreDocs. length; i++) { Document hitDoc = isearcher.doc(hits. scoreDocs[i]. doc); assertEquals("This is the text to be indexed." , hitDoc.get("fieldname")); } // 测试短语 query = parser.parse("\"to be\""); assertEquals (1, isearcher.search(query, null, 1).totalHits); //记得手动关闭 isearcher.close(); ireader.close(); directory.close(); } }
Document.add()方法流程
这个方法主要功能是将field字段和值保存到缓存中去,等待close()方法调用时写入文件。其中为了增加效率启用了多线程创建索引分词。分词组件可以自己实现只要继承Analyzer类。在分词组件里面重载incrementToken(不大记得好像是)或者自己实现一个类继承Tocken,在类里面重载incrementToken方法。这样,如果索引字段的定义了需要分词的话,就会调用你重载的这个方法,以此实现自定义分词效果。
public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException;
看了4.9+的代码,这个方法以及被定义为final。作者开发了另一个方法来提供用户重载,实现一样效果。
protected Analyzer.TokenStreamComponents createComponents(String fieldName, Reader reader);
下面贴一个程序运行的关键代码,以及基于4.7.0实现的一个Analyzer.
//保证多个进程同时读取Directory不出问题。对一个lockFactory的引用来锁定文件 public abstract class Directory implements Closeable { protected LockFactory lockFactory; } //锁定文件,因为采用多个线程同时进行分词,同时只能有一个线程对缓存进行读写 public abstract class LockFactory { public abstract Lock makeLock(String lockName); abstract public void clearLock(String lockName) throws IOException; } //保存索引文件的原文档 public final class Document implements java.io.Serializable { List<Fieldable> fields = new ArrayList<Fieldable>(); } //分词组件,有2个重载方法。功能:1、分词。2、停词。3、去掉标点。可以自己实现分词 public final class MockAnalyzer extends Analyzer { private final int pattern; private final boolean lowerCase; private final CharArraySet filter; private final boolean enablePositionIncrements; private int positionIncrementGap; private final Random random; private Map<String,Integer > previousMappings = new HashMap<String,Integer>(); private boolean enableChecks = true; private int maxTokenLength = MockTokenizer.DEFAULT_MAX_TOKEN_LENGTH ; maybePayload() { //影响词的评分 token.setPayload(new PayLoad((Field)_id.getByte())); } //这个方法返回一个TokenStreamComponents,设置reader,filters,token。(lucene4.10这个方法为final不可继承) public TokenStream reusableTokenStream(String fieldName, Reader reader) throws IOException { @SuppressWarnings("unchecked" ) Map<String,SavedStreams> map = (Map) g etPreviousTokenStream(); if (map == null) { map = new HashMap<String,SavedStreams>(); setPreviousTokenStream(map); } SavedStreams saved = map.get(fieldName); if (saved == null) { saved = new SavedStreams(); saved.tokenizer = new MockTokenizer(reader, pattern, lowerCase, maxTokenLength); saved.tokenizer.setEnableChecks( enableChecks); StopFilter filt = new StopFilter(LuceneTestCase.TEST_VERSION_CURRENT , saved.tokenizer , filter); filt.setEnablePositionIncrements(enablePositionIncrements ); //这里用的是责任链模式。类似saved.filter=A,A.filter=B,B..filter=c以此类推 saved.filter = filt; //是否使用跳跃表,不设置的话,如果索引一旦增长(根据分词判断是否使用同一个字典链表)过长,lucene会自动使用。 saved.filter = maybePayload(saved. filter, fieldName); //关键是这一行,将filter放入map,可以放入多个,类型为TokenFilter map.put(fieldName, saved); return saved. filter; } else { saved.tokenizer.reset (reader); return saved. filter; } } } //filter超类 public class Token { //默认对是否进行使用跳跃表的实现 private Payload payload; }
writer.close()方法的流程(用画图工具画的,超级烂。下次引以为戒)
关键的一部分代码:
//创建、写入文件segments public class IndexWriter implements Closeable, TwoPhaseCommit { //这里创建segments.gen,segments_N文件以及保存数据 private synchronized final void finishCommit() throws CorruptIndexException, IOException { pendingCommit .finishCommit(directory); } //入口 private void closeInternal(boolean waitForMerges) throws CorruptIndexException, IOException { //创建各种文件,(除segments*,.fdt.fdx),先组装数据,后合并数据,写入文件操作 flush(waitForMerges, true); //会调用到finishCommit() commitInternal(null); } }
英文单词大小写处理
lucene用他自带的standardAnalyzer在建立索引的时候是区分大小写的。在查询query的时候会通通转成小写,导致查询不到。那么可以复制一份源代码,放到本地改一下。调用本地就可以
protected TokenStreamComponents createComponents(final String fieldName, final Reader reader) { final StandardTokenizer src = new StandardTokenizer(matchVersion, reader); src.setMaxTokenLength(maxTokenLength); src.setReplaceInvalidAcronym(replaceInvalidAcronym); TokenStream tok = new StandardFilter(matchVersion, src); //注释掉这一句 //tok = new LowerCaseFilter(matchVersion, tok); tok = new StopFilter(matchVersion, tok, stopwords); return new TokenStreamComponents(src, tok) { @Override protected boolean reset(final Reader reader) throws IOException { src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength); return super.reset(reader); } };
参考:
因为lucene虽然版本升级,方法上有很多改变,我感觉用户体验明显好多了。但是目前他整体的架构没看得大改变。所以以前的一些书籍还是可以看得。记录一下文档地址,这是一本很好的书:http://www.open-open.com/doc/view/f92fa668d8b84626abd20a05b6eb014e
发表评论
-
(转)SPDY、HTTP/2、QUIC协议
2015-04-27 19:53 10911 SPDY协议 1.1 概述SPDY为s ... -
svn与apache dbd整合
2015-04-23 14:54 587准备工作 cd .. bzip2 -dc temp/apr- ... -
mybatis报找不到类
2015-03-26 17:36 2335调用mybatis时参数类型为一个包含动态内部类的参数类型,那 ... -
NIO和NodeJs中基于事件的异步调用
2015-03-24 15:33 782异步 目前的异步执行不管是js还是java,都并不是真正的异步 ... -
各种可用的util类
2015-03-21 10:59 0在jdk和spring中有许多我们可以直接使用的util类。 ... -
jvm学习(笔记)
2015-03-17 21:56 4271、jvm规范 2、Oracle Jdk 编译机制 ... -
本地缓存实现
2015-03-11 15:59 570最近做了个东西,使用的数据是根据元数据进行读取和加工,加工后又 ...
相关推荐
Lucene一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎
它通过浅显的语言、大量的图注、丰富的代码示例,以及清晰的结构为读者呈现出作为优秀开源项目的Lucene 所体现的强大功能。全书共10章,分为两大部分。第1部分Lucene的核心,着重于Lucene的核心API介绍,并按照把...
本书深入浅出地介绍了lucene 一个开源的使用java语言编写的全文搜索引擎开发包 它通过浅显的语言 大量的图注 丰富的代码示例 以及清晰的结构为读者呈现出作为优秀开源项目的lucene所体现的强大功能 全书共10章 分为...
Lucene学习总结之一:全文检索的基本原理 Lucene学习总结之二:Lucene的总体架构 Lucene学习总结之三:Lucene的索引文件格式(1) Lucene学习总结之三:Lucene的索引文件格式(2) Lucene学习总结之三:Lucene的...
本文主要是研究了全文检索技术的基本原理以及Lucene的架构和工作原理,并介绍了基于Lucene的实时全文检索引擎的设计实现过程。并提供了一个基于Web的简单实现。最后通过实验的方式,对实现的实时全文检索引擎的性能...
Lucene.net 系列教程,讲解Lucene.net的基本架构
本系列文章将详细描述几乎最新版本的Lucene的基本原理和代码分析。 其中总体架构和索引文件格式是Lucene 2.9的,索引过程分析是Lucene 3.0的。 鉴于索引文件格式没有太大变化,因而原文没有更新,原理和架构的文章中...
它通过浅显的语言、大量的图注、丰富的代码示例,以及清晰的结构为读者呈现出作为优秀开源项目的Lucene所体现的强大功能。全书共10章,分为两大部分。第1部分Lucene的核心,着重于Lucene的核心API介绍,并按照把...
1.1 Lucene学习总结之一:全文检索的基本原理 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Lucene学习总结之二:Lucene的总体架构 . . . . . . . . . . . . ...
Lucene API的介绍,适合入门的人学习.包括全文索引文件的基本结构.
一、 全文检索的基本概念 (1)、数据总体分为两种:结构化数据和非结构化数据。 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等...
该系统实现了urban公交线路搜索的基本功能,页面简洁且交互良好,搜索速度较快,代码结构清晰易理解。但是也存在一定缺点,如站点信息较少,无实时信息如可达线路,安全和稳定性也较差,不适合直接商业应用。 总之,该java...
整个系统的架构可以分为前端和后端两部分,前端负责接收用户输入并向后端发送搜索请求,后端则负责处理搜索请求,从 Lucene 索引中检索相关的公交信息,并返回给前端展示。同时,后端还需要实现定时任务来更新 ...
分词效率: 第一次分词需要1-2秒(读取词典),之后速度基本与Lucene自带分词持平 运行环境: Lucene 1.9+ 内存消耗: 30M+ 1.4.0 —— 2006-08-21 增加词典的动态扩展能力 1.3.3 —— 2006-07...
jpa-lucene-spring-demo Javalobby上的完整文章: : 也在博客上: : 使用JPA,Lucene,Spring,DBUnit和JMockit的演示项目-持久并搜索... 该示例很简单,但是说明了如何连接基础结构以集成Lucene和JPA的基本概念。
Lucene是一个强大的全文索引引擎工具包, 它的全文检索技术是信息检索领域广泛使用的基本技术, 具有访问索引时间快、多用户访问、跨平台使用的特点。介绍了一个高性能的全文检索引擎——Lucene开源系统,详细分析了...
面试官心理分析 在搜索这块,lucene 是最流行的搜索库。几年前业内一般都问,你了解 lucene 吗?你知道倒排索引的原理吗?现在早已经 out 了,因为现在很多项目都是...就看看你对分布式搜索引擎架构的一个基本理解。
垂直化的搜索引擎在分布式系统中的使用,包括搜索引擎的基本原理、Lucene详细的使用介绍,以及基于Lucene的开源搜索引擎工具Solr的使用。 2.1 分布式缓存 60 2.1.1 memcache简介及安装 60 2.1.2 memcache ...
后文的四种基本架构中将逐一介绍应用到的其它套件。 Elasticsearch是实时全文搜索和分析引擎,提供搜集、分析、存储数据三大功能;是一套开放REST和JAVA API等结构提供高效搜索功能,可扩展的分布式系统。它构建于...
关于solr的一些基础入门,基于solr6.5,了解之后可以基本上架构出属于自己的搜索引擎