`
nj_link
  • 浏览: 10866 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

lucene基本架构

    博客分类:
  • java
阅读更多
lucene各个模块用途

建立索引和检索图解

以一个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
  • 大小: 175.1 KB
  • 大小: 4.2 KB
  • 大小: 241.8 KB
  • 大小: 13.4 KB
  • 大小: 14.9 KB
  • 大小: 88 KB
分享到:
评论

相关推荐

    lucene基本包

    这个“lucene基本包”包含了Lucene的核心组件,是理解和使用Lucene进行信息检索的基础。 1. **全文检索引擎架构** Lucene的核心理念是建立索引,以便快速查找文档中的信息。它通过将文本数据转换成便于搜索的结构...

    lucene-3.0.0-src.zip

    一、Lucene基本架构 1. 文档索引:Lucene的核心工作是将非结构化的文本数据转换为结构化的索引。这一过程包括分词(Tokenization)、词干提取(Stemming)和停用词处理(Stop Word Filtering),以及创建倒排索引...

    Lucene5.2.1jar

    一、Lucene基本架构 1. 文档索引:Lucene首先对文档进行索引,将文本数据转换成便于搜索的数据结构。这个过程包括分词(Tokenization)、词干提取(Stemming)、停用词处理(Stop Word Removal)等预处理步骤,以及...

    lucene基本使用

    一、Lucene的架构与工作原理 Lucene的核心概念包括文档(Document)、字段(Field)、索引(Index)和查询(Query)。首先,每个文档由一个或多个字段组成,字段内可以包含文本、数字或其他类型的数据。接着,...

    lucene索引结构原理

    2. **词项(Term)**:每个分词后的词汇单元称为词项,是Lucene索引的基本单位。词项由一个词典中的词汇(如“apple”)和文档中出现的位置(或位置编码)组成。 3. **词典(Dictionary)**:词典是所有唯一词项的...

    lucene索引结构原理.docx

    而在Lucene中,基本单位是Document,它同样由多个字段组成,但Lucene索引的是这些字段的内容,以加速文本检索。 - **索引构建**:Lucene支持增量索引和批量索引,可以处理数据源的小幅变化或大规模数据。数据库通常...

    Lucene搜索引擎开发权威经典

    通过阅读书中的第1章“LUCENE基础”,读者可以建立起对Lucene基本架构和工作流程的初步认识,为进一步的学习打下坚实基础。 总之,《Lucene搜索引擎开发权威经典》是一本全面介绍Lucene的书籍,适合想要从事搜索...

    lucene API最基本应用

    - **索引(Index)**: Lucene 首先需要对文档进行索引,将文本数据转换为可搜索的结构。索引是倒排索引,其中每个单词都指向包含该词的文档列表。 - **文档(Document)**: 文档是 Lucene 中的基本单位,可以代表...

    lucene基本使用,适合初学者

    ### Lucene基本使用详解 #### 一、概述 在当今数据爆炸的时代,如何从海量的信息中快速找到所需的内容成为了一项重要技能。全文检索技术便应运而生,旨在提高信息检索的效率与准确度。Lucene是一款由Apache基金会...

    lucene3.6.1源码

    一、Lucene基本架构 Lucene的核心架构主要包括以下几个关键组件: 1. 文档(Document):文档是信息的基本单元,可以包含多个字段(Field),如标题、内容等。每个字段有其特定的类型,如文本、日期等。 2. 索引...

    LUCENE搜索引擎基本工作原理

    **LUCENE搜索引擎基本工作原理** Lucene是一个开源的全文搜索引擎库,被广泛应用于构建复杂的搜索引擎系统。它的设计目标是高效、灵活且可扩展。理解Lucene的工作原理有助于开发人员更好地利用这一强大的工具。 **...

    lucene 数据库

    该文档详细阐述了Lucene的架构设计,包括其核心组件如Analyzer(分析器)、Document(文档)、IndexWriter(索引写入器)和Searcher(搜索器)的工作原理。理解这些组件如何协同工作,有助于你更好地利用Lucene进行...

    lucene

    一、Lucene的基本架构 Lucene的核心架构主要分为三个部分:索引(Indexing)、查询(Query)和搜索(Searching)。首先,索引过程将原始文档转换为倒排索引(Inverted Index),这是一个经过优化的数据结构,便于...

    lucene3源码分析

    - **基本概念**:介绍Lucene索引文件的基本术语和概念。 - **基本类型**:定义了索引文件中使用的数据类型。 - **基本规则**:阐述了文件格式设计的基本原则。 - **具体格式**: - **正向信息**:包括段元数据、...

    Annotated Lucene 中文版 Lucene源码剖析

    通过阅读《Annotated Lucene 中文版 Lucene源码剖析》,读者不仅能掌握Lucene的基本使用,还能深入了解其底层原理,从而更好地利用和扩展这个强大的搜索工具。 总之,对于想要提升信息检索技术的Java开发者来说,这...

    Lucene简介.介绍

    通过学习 Lucene,开发者不仅可以掌握全文检索的基本原理,还能了解如何设计高效的索引结构,以及如何根据特定需求定制搜索功能。例如,你可以自定义查询分析器、实现删除操作、扩展排序机制,以及利用 Lucene 的 ...

    Lucene资料大全(包括Lucene_in_Action书等)

    2. **索引构建**:Lucene将文档转换为倒排索引结构,这是一种高效的数据结构,允许快速查找包含特定词汇的文档。 3. **搜索查询**:用户可以通过QueryParser或直接构造Query对象来创建搜索请求。Lucene支持布尔查询...

    深入了解Lucene之一 系统结构分析.pptx

    **深入理解Lucene:系统结构解析** Lucene是一款开源的全文搜索引擎库,广泛应用于各种信息检索系统中。本文将从系统结构、源码组织、数据流及其相互关系等多个角度,帮助读者深入理解Lucene的核心机制。 ### **1....

    Lucene的原理完整版pdf

    ### 一、Lucene基本概念 1. **索引**:Lucene首先对文本进行索引,将文本内容转换为一系列可搜索的结构。索引过程包括分词(Tokenization)、词干提取(Stemming)、停用词处理(Stop Word Removal)等步骤。 2. *...

    lucene in action英文版 lucene 3.30包

    这本书详细讲解了Lucene的各个方面,包括安装、基本用法、高级特性和实际应用案例。书中还包含了大量代码示例,帮助读者更好地理解和实践Lucene。 8. **压缩包中的资源** "lucene in action.pdf" 是《Lucene in ...

Global site tag (gtag.js) - Google Analytics