`
liyunqiangyq
  • 浏览: 30444 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

如何读取Lucene索引数据

阅读更多

Lucene源码分析(1) -- 如何读取Lucene索引数据

原文:http://lqgao.spaces.live.com/blog/cns!3BB36966ED98D3E5!408.entry?_c11_blogpart_blogpart=blogview&_c=blogpart#permalink
终于清楚如何用读Lucene的索引 :-)。本文要介绍一下如何利用IndexReader获取信息。为什么要读索引呢?因为我需要实现这些功能:
(1) 统计term在整个collection中的文档频度(document frequency, DF);
(2) 统计term在整个collection中出现的词次(term frequency in whole collection);
(3) 统计term在某个文档中出现的频度(term frequency, TF);
(4) 列出term在某文档中出现的位置(position);
(5) 整个collection中文档的个数;

那么为什么要用到这些数据呢?这些数据是实现TR(Text Retrieval,文本检索)的必备的“原料”,而且是经过加工的。在检索之前,只有原始文本(raw data);经过索引器(indexer)的处理之后,原始文本变成了一个一个的term(或者token),然后被indexer纪录下来所在的位置、出现的次数。有了这些数据,应用一些模型,就可以实现搜索引擎实现的功能——文本检索。

聪明的读者您可能会说,这看起来似乎很好做,不过就是计数(count)么。不错,就是计数,或者说是统计。但是看似简单的过程,如果加上空间(内存容量)的限制,就显得不那么简单了。假设如果每篇文档有100个term,每个term需要存储10字节信息,存1,000,000篇文档需要 10x100x10^6=10^9=2^30字节,也就是1GB。虽然现在1G内存不算什么,可是总不能把1GB的数据时时刻刻都放入内存吧。那么放入硬盘好了,现在需要用数据的时候,再把1GB数据从硬盘搬到内存。OK,可以先去冲杯咖啡,回来在继续下面的操作。这是1,000,000的文档,如果更多一点呢,现在没有任何辅助数据结构的方式,会导致很差的效率。

Lucene的索引会把数据分成段,并且在需要的时候才读,不需要的时候就让数据乖乖地呆在硬盘上。Lucene本身是一个优秀的索引引擎,能够提供有效的索引和检索机制。文本的目的是,介绍如用利用Lucene的API,如何从已经建好的索引的数据中读取需要的信息。至于Lucene如何使用,我会在后续的文章中逐渐介绍。

我们一步一步来看。这里建设已经有实现建好索引,存放在index目录下。好,要读索引,总得先生成一个读索引器(即Lucene中IndexReader的实例)。好,写下面的程序(程序为C#程序,本文使用DotLucene)。
IndexReader reader;
问题出来了,IndexReader是一个abstract类,不能实例化。那好,换派生类试试看。找到IndexReader的两个孩子——SegmentReader和MultiReader。用哪个呢?无论是哪个都需要一大堆参数(我是颇费了周折才搞清楚它们的用途,后面再解释),似乎想用Lucene的索引数据不是那么容易啊。通过跟踪代码和查阅文档,我终于找到使用IndexReader的钥匙。原来IndexReader有一个“工厂模式”的static interface——IndexReader.Open。定义如下:
#0001  public static IndexReader Open(System.String path)
#0002  public static IndexReader Open(System.IO.FileInfo path)
#0003  public static IndexReader Open(Directory directory)
#0004  private static IndexReader Open(Directory directory, bool closeDirectory)
其中有三个是public的接口,可供调用。打开一个索引,就是这么简单:
#0001  IndexReader reader = IndexReader.Open(index);
实际上,这个打开索引经历了这样的一个过程:
#0001  SegmentInfos infos = new SegmentInfos();
#0002  Directory directory = FSDirectory.GetDirectory(index, false);
#0003  infos.Read(directory);
#0004  bool closeDirectory = false;
#0005  if (infos.Count == 1)
#0006  {
#0007   // index is optimized
#0008   return new SegmentReader(infos, infos.Info(0), closeDirectory);
#0009  }
#0010  else
#0011  {
#0012   IndexReader[] readers = new IndexReader[infos.Count];
#0013   for (int i = 0; i < infos.Count; i++)
#0014    readers[i] = new SegmentReader(infos.Info(i));
#0015   return new MultiReader(directory, infos, closeDirectory, readers);
#0016  }
首先要读入索引的段信息(segment information, #0001~#0003),然后看一下有几个段:如果只有一个,那么可能是优化过的,直接读取这一个段就可以(#0008);否则需要一次读入各个段(#0013~#0014),然后再拼成一个MultiReader(#0015)。打开索引文件的过程就是这样。

接下来我们要看看如何读取信息了。用下面这段代码来说明。
#0001  public static void PrintIndex(IndexReader reader)
#0002  {
#0003      //显示有多少个document
#0004      System.Console.WriteLine(reader + "\tNumDocs = " + reader.NumDocs());
#0005      for (int i = 0; i < reader.NumDocs(); i++)
#0006      {
#0007          System.Console.WriteLine(reader.Document(i));
#0008      }
#0009  
#0010      //枚举term,获得<document, term freq, position* >信息
#0011      TermEnum termEnum = reader.Terms();
#0012      while (termEnum.Next())
#0013      {
#0014          System.Console.Write(termEnum.Term());
#0015          System.Console.WriteLine("\tDocFreq=" + termEnum.DocFreq());
#0016  
#0017          TermPositions termPositions = reader.TermPositions(termEnum.Term());
#0018          int i = 0;
#0019          int j = 0;
#0020          while (termPositions.Next())
#0021          {
#0022              System.Console.WriteLine((i++) + "->" + " DocNo:" + termPositions.Doc() + ", Freq:" + termPositions.Freq());
#0023              for (j = 0; j < termPositions.Freq(); j++)
#0024                  System.Console.Write("[" + termPositions.NextPosition() + "]");
#0025              System.Console.WriteLine();
#0026          }
#0027  
#0028          //直接获取 <term freq, document> 的信息
#0029          TermDocs termDocs = reader.TermDocs(termEnum.Term());
#0030          while (termDocs.Next())
#0031          {
#0032              System.Console.WriteLine((i++) + "->" + " DocNo:" + termDocs.Doc() + ", Freq:" + termDocs.Freq());
#0033          }
#0034      }
#0035  
#0036      // FieldInfos fieldInfos = reader.fieldInfos;
#0037      // FieldInfo pathFieldInfo = fieldInfos.FieldInfo("path");
#0038  
#0039      //显示 term frequency vector
#0040      for (int i = 0; i < reader.NumDocs(); i++)
#0041      {
#0042          //对contents的token之后的term存于了TermFreqVector
#0043          TermFreqVector termFreqVector = reader.GetTermFreqVector(i, "contents");
#0044  
#0045          if (termFreqVector == null)
#0046          {
#0047              System.Console.WriteLine("termFreqVector is null.");
#0048              continue;
#0049          }
#0050  
#0051          String fieldName = termFreqVector.GetField();
#0052          String[] terms = termFreqVector.GetTerms();
#0053          int[] frequences = termFreqVector.GetTermFrequencies();
#0054  
#0055          System.Console.Write("FieldName:" + fieldName);
#0056          for (int j = 0; j < terms.Length; j++)
#0057          {
#0058              System.Console.Write("[" + terms[j] + ":" + frequences[j] + "]");
#0059          }
#0060          System.Console.WriteLine();
#0061      }
#0062      System.Console.WriteLine();
#0063  }
#0004 计算document的个数
#0012~#0034 枚举collection中所有的term
其中#0017~#0026 枚举每个term在出现的document中的所有位置(第几个词,从1开始计数);#0029~#0033 计算每个term出现在哪些文档和相应的出现频度(即DF和TF)。
#0036~#0037在reader是SegmentReader类型的情况下有效。
#0040~#0061可以快速的读取某篇文档中出现的term和相应的频度。但是这部分需要在建索引时,设置storeTermVector为true。比如
doc.Add(Field.Text("contents", reader, true));
其中的第三项即是。默认为false。

有了这些数据,就可以统计我需要的数据了。以后我会介绍如何建立索引,如何应用Lucene。

0
0
分享到:
评论

相关推荐

    Lucene索引数据分析器

    **Lucene索引数据分析器** Lucene是一款强大的开源全文搜索引擎库,由Apache软件基金会开发,广泛应用于各种数据检索系统。它的核心功能在于高效地构建、管理和搜索文本索引,为开发者提供快速的数据查询能力。本篇...

    Lucene读取索引文件

    《深入理解Lucene:解析索引文件的读取》 ...总之,掌握Lucene索引文件的读取是提升Lucene应用能力的关键一步。通过对索引结构、API用法以及查询优化的深入理解,开发者可以构建出更加高效、准确的全文检索系统。

    Lucene索引器实例

    **Lucene索引器实例详解** Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发,被广泛应用于各种搜索引擎的构建。它提供了一个高级的、灵活的、可扩展的接口,使得开发者能够轻松地在应用程序中实现全文...

    lucene索引查看工具及源码

    - **索引读取**:了解 Luke 是如何使用 Lucene 的 `IndexReader` 和 `Directory` 接口来访问和加载索引的。 - **字段和文档处理**:观察 Luke 如何获取和显示文档字段,以及如何解析和展示不同类型的字段值。 - **...

    Lucene索引和查询

    **Lucene索引和查询** Lucene是Apache软件基金会的开放源码全文搜索引擎库,它提供了文本检索的核心工具,使得开发者能够快速构建自己的搜索应用。本项目中的代码旨在展示如何利用Lucene对多个文件夹下的数据进行...

    Lucene 索引的简单使用

    以上就是关于“Lucene索引的简单使用”的详细介绍,包括其核心概念、创建和查询索引的步骤以及一些高级特性。希望对你理解和应用Lucene有所帮助。在实际开发中,可以根据需求选择合适的Analyzer,优化索引策略,以...

    lucene索引文件格式介绍

    了解这些文件格式后,我们还要知道Lucene索引中使用的基本数据类型,如Byte、UInt32、UInt64和VInt。VInt是一种变长整数类型,它根据数值大小动态占用字节,有效地节省了存储空间。 总的来说,Lucene的索引文件格式...

    luke源码--查看lucene索引文件

    《深入理解Luke:洞察Lucene索引文件》 在信息技术领域,搜索引擎的高效运作离不开对数据的快速检索,而Lucene作为开源全文检索库,扮演了核心角色。在这个过程中,Luke工具提供了一种直观的方式,让我们能够查看和...

    lucene 索引小示例

    《Lucene索引小示例解析》 Lucene是一个高性能、全文检索库,它由Apache软件基金会开发并维护。在Java编程环境中,Lucene被广泛应用于构建搜索功能,特别是对于大量文本数据的高效检索。本篇文章将通过一个简单的小...

    如何将Lucene索引写入Hadoop?

    标题 "如何将Lucene索引写入Hadoop" 指涉的是在大数据处理场景下,如何利用Apache Lucene的全文检索功能与Apache Hadoop的分布式计算能力相结合,实现高效的数据检索。Apache Lucene是一个高性能、全文本搜索库,而...

    lucene索引优化多线程多目录创建索引

    通过对“lucene_multiThreadIndex”压缩包的学习,你将掌握如何在Lucene中实现多线程索引,从而提高大型数据集的索引构建速度。通过实践,你可以更好地理解和应用这些技术,优化你的信息检索系统。

    Lucene索引管理器(基于Luke修改而来)

    **Lucene索引管理器(基于Luke修改而来)** Lucene是Apache软件基金会的一个开源全文检索库,它提供了强大的文本搜索功能。而Luke是Lucene的可视化工具,它允许开发者查看和操作Lucene索引,包括文档内容、字段、分词...

    Lucene索引分析工具

    **Lucene索引分析工具详解** Lucene是一个高性能、全文本搜索库,它为开发者提供了在应用程序中实现全文检索功能的基础。在这个场景中,我们关注的是一个专门针对Lucene.net的索引分析工具,该工具被称为"Lucene...

    基于Lucene索引的分析与实现

    创建索引时,Lucene会读取输入文档,进行分词处理,然后为每个词创建倒排索引。搜索时,用户输入的查询会被转换成词项列表,然后Lucene会查找这些词项在索引中的对应信息,通过评分算法确定相关性,最终返回最相关的...

    lucene 4.7.2 Demo

    创建索引是全文检索的基础,它涉及将文本数据结构化为Lucene可以理解和查询的形式。开发者可以通过Analyzer类来处理输入的文本,进行分词、去除停用词等预处理步骤。然后,使用Document类表示要索引的数据,Field类...

    LUCENE索引搜索数据库技术汇总

    - **数据库集成**: 通过JDBC或其他方式将数据库中的数据导入Lucene索引,实现高效全文检索。 - **联合查询(Hybrid Search)**: 结合SQL查询与Lucene的全文搜索,提供更强大的搜索能力。 综上所述,Lucene提供了...

    Lucene索引搜索简介以及入门实例源码.rar

    **Lucene索引搜索简介** Lucene是Apache软件基金会下的一个开源全文搜索引擎库,它提供了高性能、可扩展的文本搜索功能。Lucene并不是一个完整的搜索引擎,而是一个工具集,允许开发人员在自己的应用程序中实现搜索...

    Lucene3.0创建索引

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

    lucene实现索引查询

    3. **创建索引读取器**:`IndexReader`用于读取索引,从中获取文档信息。 4. **创建QueryParser**:QueryParser解析用户的查询字符串,生成一个Query对象。需要指定查询字段的名称和分词器。 5. **解析查询**:`...

    lucene 索引工具源码(桌面版)

    结合“CreateIndex”这个文件名,我们可以推测这个工具可能包含了索引创建的整个流程,包括读取数据源、分词、建立倒排索引以及保存索引到磁盘。通过阅读源码,我们可以学习如何配置和使用这些组件,以及如何优化...

Global site tag (gtag.js) - Google Analytics