【问题标题】:How does Lucene (Solr/ElasticSearch) so quickly do filtered term counts?Lucene (Solr/ElasticSearch) 是如何快速计算过滤词条的?
【发布时间】:2014-12-11 06:01:49
【问题描述】:

从数据结构的角度来看,Lucene (Solr/ElasticSearch) 是如何如此快速地进行过滤术语计数的?例如,给定所有包含单词“bacon”的文档,找出这些文档中所有单词的计数。

首先,作为背景,我了解 Lucene 依赖于类似于 CONCISE 的压缩位数组数据结构。从概念上讲,这个位数组为每个不匹配术语的文档保存一个 0,为每个匹配一个术语的文档保存一个 1。但是很酷/很棒的部分是这个数组可以被高度压缩并且在布尔运算中非常快。例如,如果您想知道哪些文档包含术语“red”和“blue”,那么您获取对应于“red”的位数组和对应于“blue”的位数组,并将它们相加得到对应于的位数组匹配文件。

但是 Lucene 如何快速确定文档中匹配“bacon”的所有单词的计数?在我幼稚的理解中,Lucene 必须将与 bacon 关联的位数组与其他每个单词的位数组相结合。我错过了什么吗?我不明白这如何有效。此外,这些位阵列是否必须从磁盘中取出?这听起来更糟!

魔法效果如何?

【问题讨论】:

  • 您能链接到您正在谈论的功能的 JavaDoc 吗?我正在查找“过滤后的术语计数”,结果为空。

标签: data-structures solr lucene elasticsearch


【解决方案1】:

您可能已经知道这一点,但说 Lucene 使用倒排索引并没有什么坏处。在这种索引技术中,制作了所有文档中出现的每个单词的字典,并针对每个单词存储有关该单词出现的信息。像这张图片

为了实现这一点,Lucene 以不同的文件格式存储文档、索引及其元数据。点击此链接了解文件详情http://lucene.apache.org/core/3_0_3/fileformats.html#Overview

如果您阅读了document numbers 部分,每个文档都有一个内部 ID,因此当找到带有单词“consign”的文档时,lucene 引擎会引用它的元数据。 请参阅概述部分以查看哪些数据保存在不同的 lucene 索引中。 现在我们有了一个指向存储文档的指针,Lucene 可能会通过以下方式之一获取它

  1. 如果存储文档的话,真正统计字数
  2. 使用术语字典、频率和邻近度数据来获取计数。

最后,您使用哪个 API 来“快速确定所有单词的计数”

图片归功于http://leanjavaengineering.wordpress.com/

在这里查看索引文件格式http://lucene.apache.org/core/8_2_0/core/org/apache/lucene/codecs/lucene80/package-summary.html#package.description

【讨论】:

  • 我不知道这个 API 在 Lucene 本身中是什么,但在 Solr 或 ElasticSearch 中,我会使用方面来做到这一点。基本上我会运行“委托”查询,然后对仅在包含委托的文档中存在的所有标记进行构面计数
【解决方案2】:

不涉及位集:它是一个倒排索引。每个术语都映射到一个文档列表。在 lucene 中,算法对这些“列表”的迭代器起作用,因此迭代器中的项目是按需读取的,而不是一次读取。

此图显示了一个非常简单的合取算法,它只使用了 next() 操作:http://nlp.stanford.edu/IR-book/html/htmledition/processing-boolean-queries-1.html

在幕后,它很像 lucene 中的这张图。我们的列表是 delta-encoded 和 bitpacked,并增加了一个 skiplist,它允许我们比上述算法更有效地相交(通过额外的 advance() 操作)。

DocIDSetIterator 就是 lucene 中的这个“枚举器”。它有两个主要方法,next() 和advance()。是的,您确实可以决定读取整个列表 + 将其转换为内存中的位集,并在该内存位集上实现此迭代器。如果您使用 CachingWrapperFilter,就会发生这种情况。

【讨论】:

  • 因此,给定 listOfDocIdsThatMatchQuery 和倒排索引中的给定 docIdList,计算在结束跳过列表之前,我们可以为 listOfDocIdsThatMatchQuery 中的每个 id 执行多少次 docIdList.Advance(id)。无论计数是什么,都是该术语的方面的值。听起来对吗?
  • 所有这些都保留在 RAM 中吗?还是我们从磁盘上拉出一些东西?我想知道当语料库大到无法再放入内存时会发生什么。
  • 如果您的操作系统缓存了页面,则页面在 RAM 中 :) 它本质上类似于 BufferedInputStream:我们一次读取 128 个文档块,其余的则一次压缩一个文档。您还可以使用 skiplist 数据查找流的后半部分(它的块对齐,所以如果一个词很少见并且有
猜你喜欢
  • 1970-01-01
  • 2012-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多