从数据结构的角度来看,Lucene(Solr / ElasticSearch)如何快速地过滤术语计数?例如,给出所有包含"培根"找到这些文件中所有单词的计数。
首先,对于背景,我知道Lucene依赖于类似于CONCISE的压缩位数组数据结构。从概念上讲,这个位数组对于每个与术语不匹配的文档保持0,对于与术语匹配的每个文档保持1。但很酷/很棒的部分是这个数组可以高度压缩,并且在布尔操作时非常快。例如,如果您想知道哪些文档包含术语" red"和"蓝"然后你抓住对应于" red"的位数组。并且位数对应于" blue"和它们一起得到一个与匹配文档相对应的数组。
但是,Lucene如何快速确定与#34;培根"?相匹配的文件中的所有单词的计数?在我天真的理解中,Lucene必须将与培根相关的位数组和AND它与每个单独的其他单词的位数组相关联。我错过了什么吗?我不明白这是多么有效。此外,这些位阵列是否必须从磁盘中取出?听起来更糟糕!
神奇的工作如何?
答案 0 :(得分:9)
你可能已经知道这一点但是说Lucene使用倒排索引并不会有什么坏处。在该索引技术中,制作出在所有文档中出现的每个单词的字典,并且针对每个单词存储关于单词出现的信息。类似这样的图像
为实现此目的,Lucene以不同的文件格式存储文档,索引及其元数据。请点击此链接查看文件详情http://lucene.apache.org/core/3_0_3/fileformats.html#Overview
如果您阅读document numbers
部分,则会为每个文档提供一个内部ID,因此当找到带有“consign”字样的文档时,lucene引擎会引用它的元数据。
请参阅概述部分以查看在不同的lucene索引中保存的数据。
现在我们有一个指向存储文档的指针,Lucene可能会通过以下方式之一获取它
最后,您使用哪种API“快速确定所有单词的计数”
答案 1 :(得分:2)
没有涉及的位集:它是一个倒排索引。每个术语都映射到文档列表。在lucene中,算法处理这些"列表"的迭代器,因此来自迭代器的项目是按需读取的,而不是一次性读取。
此图显示了一个非常简单的连接算法,该算法仅使用next()操作:http://nlp.stanford.edu/IR-book/html/htmledition/processing-boolean-queries-1.html
在幕后,它就像lucene中的这个图。我们的列表是delta编码和bitpacked,并使用skiplist进行扩充,允许我们比上述算法更有效地交叉(通过额外的advance()操作)。
DocIDSetIterator就是这个"调查员"在lucene。它有两个主要方法,next()和advance()。是的,你可以决定读取整个列表并将其转换为内存中的bitset,然后在内存中的bitset上实现这个迭代器。如果您使用CachingWrapperFilter,会发生这种情况。