`
wbj0110
  • 浏览: 1610276 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Lucene 源代码剖析-8 索引是如何创建的

阅读更多

Lucene 源码剖析

4           索引是如何创建的

为了使用Lucene来索引数据,首先你比把它转换成一个纯文本(plain-texttokens的数据流(stream),并通过它创建出Document对象,其包含的Fields成员容纳这些文本数据。一旦你准备好些Document对象,你就可以调用IndexWriter类的addDocument(Document)方法来传递这些对象到Lucene并写入索引中。当你做这些的时候,Lucene首先分析(analyzer)这些数据来使得它们更适合索引。详见《Lucene In Action

  

   

4.1   索引创建示例

   下面的代码示例如何给一个文件建立索引。 

     

    // Store the index on disk
    Directory directory = FSDirectory.getDirectory(“/tmp/testindex“);
    
// Use standard analyzer
    Analyzer analyzer = new StandardAnalyzer(); 
    
// Create IndexWriter object
    IndexWriter iwriter = new IndexWriter(directory, analyzer, true);
    iwriter.setMaxFieldLength(25000);
    
// make a new, empty document
    Document doc = new Document();
    File f = 
new File(“/tmp/test.txt“);
    
// Add the path of the file as a field named ”path”.  Use a field that is 
    // indexed (i.e. searchable), but don’t tokenize the field into words.
    doc.add(new Field(“path“, f.getPath(), Field.Store.YES, Field.Index.UN_TOKENIZED));
    String text = “This is the text to be indexed.“;
    doc.add(
new Field(“fieldname“, text, Field.Store.YES,      Field.Index.TOKENIZED));
    
// Add the last modified date of the file a field named ”modified”.  Use 
    // a field that is indexed (i.e. searchable), but don’t tokenize the field
    // into words.
    doc.add(new Field(“modified“,
        DateTools.timeToString(f.lastModified(), DateTools.Resolution.MINUTE),
        Field.Store.YES, Field.Index.UN_TOKENIZED));
    
// Add the contents of the file to a field named ”contents”.  Specify a Reader,
    // so that the text of the file is tokenized and indexed, but not stored.
    // Note that FileReader expects the file to be in the system’s default encoding.
    // If that’s not the case searching for special characters will fail.
    doc.add(new Field(“contents“, new FileReader(f)));
    iwriter.addDocument(doc);
    iwriter.optimize();
    iwriter.close();

   

下面详细介绍每一个类的处理机制。

4.2       索引创建类IndexWriter

一个IndexWriter对象创建并且维护(maintains) 一条索引并生成segment,使用DocumentsWriter类来建立多个文档的索引数据,SegmentMerger类负责合并多个segment

  

4.2.1      org.apache.lucene.store.IndexWriter

一个IndexWriter对象只创建并维护一个索引。IndexWriter通过指定存放的目录(Directory)以及文档分析器(Analyzer)来构建,direcotry代表索引存储(resides)在哪里;analyzer表示如何来分析文档的内容;similarity用来规格化(normalize)文档,给文档算分(scoring);IndexWriter类里还有一些SegmentInfos对象用于存储索引片段信息,以及发生故障回滚等。以下是它们的类图:

  

 

  

  

它的构造函数(constructor)create参数(argument)确定(determines)是否一条新的索引将被创建,或者是否一条已经存在的索引将被打开。需要注意的是你可以使用create=true参数打开一条索引,即使有其他readers也在在使用这条索引。旧的readers将继续检索它们已经打开的”point in time”快照(snapshot),并不能看见那些新已创建的索引,直到它们再次打开(re-open)。另外还有一个没有create参数的构造函数,如果提供的目录(provided path)中没有已经存在的索引,它将创建它,否则将打开此存在的索引。

  

另一方面(in either case),添加文档使用addDocument()方法,删除文档使用removeDocument()方法,而且一篇文档可以使用updateDocument()方法来更新(仅仅是先执行delete在执行add操作而已)。当完成了添加、删除、更新文档,应该需要调用close方法。

  

这些修改会缓存在内存中(buffered in memory),并且定期地(periodically)刷新到(flushDirectory中(在上述方法的调用期间)。一次flush操作会在如下时候触发(triggered):当从上一次flush操作后有足够多缓存的delete操作(参见setMaxBufferedDeleteTerms(int)),或者足够多已添加的文档(参见setMaxBufferedDocs(int)),无论哪个更快些(whichever is sooner)。对被添加的文档来说,一次flush会在如下任何一种情况下触发,文档的RAM缓存使用率(setRAMBufferSizeMB)或者已添加的文档数目,缺省的RAM最高使用率是16M,为得到索引的最高效率,你需要使用更大的RAM缓存大小。需要注意的是,flush处理仅仅是将IndexWriter中内部缓存的状态(internal buffered state)移动进索引里去,但是这些改变不会让IndexReader见到,直到commit()close()中的任何一个方法被调用时。一次flush可能触发一个或更多的片断合并(segment merges),这时会启动一个后台的线程来处理,所以不会中断addDocument的调用,请参考MergeScheduler

  

构造函数中的可选参数(optional argumentautoCommit控制(controls)修改对IndexReader实体(instance)读取相同索引的能见度(visibility)。当设置为false时,修改操作将不可见(visible)直到close()方法被调用后。需要注意的是修改将依然被flushDirectory,就像新文件一样(as new files),但是却不会被提交(commit)(没有新的引用那些新文件的segments_N文件会被写入(written referencing the new files))直道close()方法被调用。如果在调用close()之前发生了某种严重错误(something goes terribly wrong)(例如JVM崩溃了),于是索引将反映(reflect)没有任何修改发生过(none of changes made)(它将保留它开始的状态(remain in its starting state))。你还可以调用rollback(),这样可以关闭那些没有提交任何修改操作的writers,并且清除所有那些已经flush但是现在不被引用的(unreferenced)索引文件。这个模式(mode)对防止(preventreaders在一个错误的时间重新刷新(refresh)非常有用(例如在你完成所有delete操作后,但是在你完成添加操作前的时候)。它还能被用来实现简单的single-writer的事务语义(transactional semantics)(“all or none”)。你还可以执行两条语句(two-phase)的commit,通过调用prepareCommit()方法,之后再调用commit()方法。这在Lucene与外部资源(例如数据库)交互的时候是很需要的,而且必须执行commitrollback该事务。

  

autoCommit设为true的时候,该writer会周期性地提交它自己的数据。已过时:注意在3.0版本中,IndexWriter将不会接收autoCommit=true,它会硬设置(hardwired)为false。你可以自己在需要的时候经常调用commit()方法。这不保证什么时候一个确定的commit会处理。它被曾经用来在每次flush的时候处理,但是现在会在每次完成merge操作后处理,如2.4版本中即如此。如果你想强行执行commit,请调用commit方法或者close这个writer。一旦一个commit完成后,新打开的IndexReader实例将会看到索引中该commit更改的数据。当以这种模式运行时,当优化(optimize)或者片断合并(segment merges)正在进行(take place)的时候需要小心地重新刷新(refresh)你的readers,因为这两个操作会绑定(tie up)可观的(substantial)磁盘空间。

  

不管(RegardlessautoCommit参数如何,一个IndexReader或者IndexSearcher只会看到索引在它打开的当时的状态。任何在索引被打开之后提交到索引中的commit信息,在它被重新打开之前都不会见到。当一条索引暂时(for a while)将不会有更多的文档被添加,并且期望(desired)得到最理想(optimal)的检索性能(performance),于是optimize()方法应该在索引被关闭之前被调用。

  

打开IndexWriter会为使用的Directory创建一个lock文件。尝试对相同的Directory打开另一个IndexWriter将会导致(lead to)一个LockObtainFailedException异常。如果一个建立在相同的DirectoryIndexReader对象被用来从这条索引中删除文档的时候,这个异常也会被抛出。

  

专家(Expert):IndexWriter允许指定(specify)一个可选的(optionalIndexDeletionPolicy实现。你可以通过这个控制什么时候优先的提交(prior commit)从索引中被删除。缺省的策略(policy)是KeepOnlyLastCommitDeletionPolicy类,在一个新的提交完成的时候它会马上所有的优先提交(prior commit)(这匹配2.2版本之前的行为)。创建你自己的策略能够允许你明确地(explicitly)保留以前的”point in time”提交(commit)在索引中存在(alive)一段时间。为了让readers刷新到新的提交,在它们之下没有被删除的旧的提交(without having the old commit deleted out from under them)。这对那些不支持“在最后关闭时才删除”语义(”delete on last close semantics)的文件系统(filesystem)如NFS,而这是Lucene的“point in time”检索通常所依赖的(normally rely on)。

  

专家(Expert):IndexWriter允许你分别修改MergePolicyMergeSchedulerMergePolicy会在该索引中的segment有更改的任何时候被调用。它的角色是选择哪一个merge来做,如果有(if any)则传回一个MergePolicy.MergeSpecificatio来描述这些merges。它还会选择merges来为optimize()做处理,缺省是LogByteSizeMergePolicy。然后MergeScheduler会通过传递这些merges来被调用,并且它决定什么时候和怎么样来执行这些merges处理,缺省是ConcurrentMergeScheduler

  

  

4.2.2 org.apache.lucene.index.DocumentsWriter

DocumentsWriter是由IndexWriter调用来负责处理多个文档的类,它通过与Directory类及Analyzer类、Scorer类等将文档内容提取出来,并分解成一组term列表再生成一个单一的segment所需要的数据文件,如term频率、term位置、term向量等索引文件,以便SegmentMerger将它合并到统一的segment中去。以下是它的类图:         

   

 

   

该类可接收多个添加的文档,并且直接写成一个单独的segment文件。这比为每一个文档创建一个segment(使用DocumentWriter)以及对那些segments执行合作处理更有效率。

  

每一个添加的文档都被传递给DocConsumer类,它处理该文档并且与索引链表中(indexing chain)其它的consumers相互发生作用(interacts with)。确定的consumers,就像StoredFieldWriterTermVectorsTermsWriter,提取一个文档的摘要(digest),并且马上把字节写入“文档存储”文件(比如它们不为每一个文档消耗(consume)内存RAM,除了当它们正在处理文档的时候)。

  

其它的consumers,比如FreqProxTermsWriterNormsWriter,会缓存字节在内存中,只有当一个新的segment制造出的时候才会flush到磁盘中。

  

一旦使用完我们分配的RAM缓存,或者已添加的文档数目足够多的时候(这时候是根据添加的文档数目而不是RAM的使用率来确定是否flush),我们将创建一个真实的segment,并将它写入Directory中去。 

 

http://www.cnblogs.com/eaglet/archive/2009/02/16/1391502.html

 
 
分享到:
评论

相关推荐

    .NET lucene 源代码

    标题中的".NET Lucene 源代码"表明我们将探讨的是如何在.NET环境下利用Lucene进行搜索引擎的开发,并且会涉及到源代码层面的解析。描述中提到的“简单易用”,揭示了Lucene的核心特性之一,即它对开发者友好,易于...

    Lucene源代码剖析

    《Lucene源代码剖析》是一本深度探讨Java版本Lucene搜索引擎库的专业书籍。Lucene是Apache软件基金会的一个开源项目,广泛应用于全文检索和信息检索领域。本书旨在通过深入解析其源代码,帮助开发者理解Lucene的工作...

    lucene.net源代码

    《深入剖析Lucene.NET:基于源代码的实例解析》 Lucene.NET,作为Apache Lucene的.NET版本,是一个高性能、全文检索库,为.NET开发者提供了强大的文本搜索功能。本实例将带您深入理解Lucene.NET的内部机制,通过源...

    lucene-5.3.1源代码

    - 通过阅读源代码,可以理解Lucene的内部工作原理,如如何构建索引、执行查询等。 - 分析器部分的源码有助于了解文本预处理过程,包括分词、去除停用词等。 - 探究查询解析器的实现,掌握如何将自然语言转化为...

    Lucene-2.3.1 源代码阅读学习

    《Lucene-2.3.1 源代码阅读学习》 Lucene是Apache软件基金会的一个开放源码项目,它是一个高性能、全文本搜索库,为开发者提供了在Java应用程序中实现全文检索功能的基础架构。本篇文章将深入探讨Lucene 2.3.1版本...

    lucene实现 源代码,里面还含有索引创建,搜索等功能

    在这个压缩包文件中,包含的源代码着重展示了如何利用Lucene进行索引创建和搜索操作,这些都是Lucene的核心功能。 首先,让我们了解一下Lucene的索引创建过程。在Lucene中,数据被转化为一种便于搜索的结构——倒排...

    CLucene源代码-Lucene的C++版本

    开发者可以查看和修改源代码,了解索引构建、查询解析、搜索执行等核心流程,这对于开发自定义的搜索引擎或扩展现有功能非常有用。通过学习CLucene,你可以掌握如何在C++中实现高效的文本分析、索引构建和搜索策略。...

    lucene-core-2.9.2.jar

    Apache采用的是Apache License 2.0,这是一种宽松的开源许可,允许用户自由地使用、复制、修改、合并、发布、分发、再授权和/或销售软件,同时也允许用户以源代码或编译后的形式分发。了解许可条款对于遵循开源社区...

    luke 源代码(luke Lucene index 索引 源代码)

    《深入理解Luke:Lucene索引查看工具的源代码解析》 Luke,作为一个开源的Lucene索引浏览器,为开发者提供了直接查看和分析Lucene索引的能力。它不仅是一个强大的工具,也是学习Lucene索引机制的重要途径。通过阅读...

    Lucene3.0创建索引

    ### Lucene3.0创建索引 在Lucene3.0中创建索引是一个关键功能,可以帮助用户快速地检索和管理大量的文本数据。本篇文章将详细介绍如何使用Lucene3.0来创建索引,并通过一个具体的例子来演示整个过程。 #### 一、...

    Lucene 3.6.2 源代码

    这个源代码版本代表了Lucene 3.x系列的最后一个稳定版本,为开发者提供了深入理解Lucene内部机制的宝贵资源。下面将详细探讨Lucene 3.6.2中的关键知识点。 1. **分词器(Tokenizers)**: Lucene的核心功能之一是...

    lucene-3.0.1库及源代码

    《深入理解Lucene 3.0.1:库与源代码解析》 Lucene是一个开源全文搜索引擎库,由Apache软件基金会开发并维护。这个“lucene-3.0.1”版本代表了Lucene在2009年的一个重要里程碑,它提供了强大的文本检索功能,被广泛...

    Lucene-core-2.0.0

    1. **Lucene概述**: Lucene是Apache软件基金会的一个开放源代码项目,它是Java语言编写的信息检索库。它提供了高级的索引和搜索功能,支持分词、布尔运算、短语搜索、近似搜索等多种搜索模式。 2. **Lucene核心组件...

    Incubating-Apache-Lucene.Net-2.0-004-11Mar07.bin.zip

    由于描述中提到“已编译,不含源代码”,这意味着提供的文件是编译后的二进制版本,用户可以直接在.NET环境中使用,而无需自行编译源代码。 Lucene.Net的核心功能包括: 1. **全文检索**:Lucene.Net支持对文本...

    lucene索引查看程序及代码

    通过阅读和分析源代码,我们可以学习到如何操作Lucene索引,以及如何构建类似的工具。 总结而言,luke作为Lucene索引的可视化工具,极大地便利了开发者对索引的理解和调试。无论是初学者还是经验丰富的开发人员,都...

    lucene第一步---5.中文分词IKAnalyzer和高亮highlighter的使用

    Lucene是Apache软件基金会的一个开放源代码项目,它是一个全文搜索引擎库,提供了文本分析、索引和搜索的基本功能。 1. **Lucene简介** Lucene是一个高性能、全文本检索库,可集成到各种系统中,用于构建强大的...

    Lucene.net-4.8.0 -new Bate.rar

    Lucene.Net提供了多种内置分析器,如标准分析器(StandardAnalyzer)、盘古分析器(PanguAnalyzer),也可自定义分析器以满足特定的语言或业务需求。 3. **文档(Document)**:文档是信息的基本单位,可以包含多个...

    lucene-2.9.4-src.zip

    《Apache Lucene 2.9.4源代码解析》 Apache Lucene是一个开源全文搜索引擎库,由Java编写,被广泛应用于各种搜索应用中...无论是对搜索技术的探索,还是在实际项目中的应用,深入研究Lucene源代码都能带来极大的收益。

    lucene-4.2.1-src.tgz

    Lucene 4.2.1是这个库的一个版本,它包含了源代码,允许开发者深入理解其工作原理,并根据需要进行定制和扩展。 在Lucene 4.2.1中,你可以找到以下关键知识点: 1. **索引构建**:Lucene的核心功能之一是能够高效...

Global site tag (gtag.js) - Google Analytics