【问题标题】:How does Lucene filter over a range of continuous valuesLucene 如何过滤一系列连续值
【发布时间】:2014-12-11 05:43:12
【问题描述】:

从数据结构的角度来看,Lucene 如何过滤一系列连续值?

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

但是 Lucene 还提供了对连续值范围的非常快速的查找,如果 Lucene 仍然使用这种相同的压缩位数组方法,我不明白这在计算或内存中是如何有效地发生的。这是我的假设,你告诉我我有多接近:Lucene 离散化连续字段并为每个这些(现在是离散的)值创建一个位数组。然后,当您想要一个跨值的范围时,您可以获取与该范围相对应的位数组,然后将它们组合在一起。由于我怀疑会有大量的数组来 AND 一起,那么也许您可以在多个粒度级别上执行此操作,以便您可以尽可能地将大块 AND 一起。

更新: 哦!我刚刚意识到另一种更快的选择。既然我们知道上面提到的离散化范围的位数组不会重叠,那么我们可以顺序存储位数组。如果我们的范围有一个开始值和结束值,那么我们可以在这个位数组的 array 中保留一个对应点的索引。此时,我们只需跳入位数组数组并开始扫描它,就好像我们正在扫描单个位数组一样。我接近了吗?

【问题讨论】:

  • 提示:一些排序是通过 FieldCache 完成的,它是索引的未倒置视图。另请参阅 DocValues。
  • 有没有机会this 回答你的问题?
  • @mindas - 谢谢,这肯定让我更接近

标签: data-structures solr lucene elasticsearch


【解决方案1】:

范围查询(例如 0 到 100)是范围内所有术语(1、2、3、4、5...)的列表的并集。问题是,如果范围必须访问许多术语,因为这意味着要处理许多短期列表。

最好只处理几个长列表(这是 lucene 的优化对象)。因此,当您使用数字字段并索引一个数字(如 4)时,我们实际上会对其进行多次冗余索引,从而以较低的精度添加一些“假术语”。这允许我们通过处理 7 个术语而不是 100 来处理 0 到 100 之类的范围:“0-63”、“64-95”、96、97、98、99、100。在此示例中,“0-63” " 和 "64-95" 是表示值范围的附加冗余项。

【讨论】:

    【解决方案2】:

    我有机会深入研究这一点。如果您不想阅读底部的这些链接,请阅读 tl;dr:

    • 在索引时,诸如1234 之类的数字被转换为多个标记,原始数字[1234] 和几个代表原始数字不太精确版本的标记:[123x][12xx] 和@ 987654331@。 (为了便于传达想法,这在一定程度上进行了简化。)
    • 在查询时,您可以利用不太精确的标记允许我们搜索标记范围这一事实。所以 Lucene 不会做幼稚的事情——通过搜索全精度术语的术语字典,提取所有匹配的数字,并对所有术语进行布尔 OR 搜索。相反,Lucene 使用了涵盖尽可能大范围的术语,并将这个更小的集合组合在一起。例如,要搜索范围从 1776 到 2015 的所有数字,Lucene 会将这些标记“或”在一起:[1776][1777][1778][1779][18xx][19xx][200x]、@ 987654339@、[2011][2012][2013][2014][2015]

    这是一个不错的步行:

    【讨论】:

      猜你喜欢
      • 2017-04-13
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-07
      相关资源
      最近更新 更多