【问题标题】:How do fulltext indexers (or caches) work?全文索引器(或缓存)如何工作?
【发布时间】:2010-11-03 20:05:35
【问题描述】:

我想知道,全文搜索系统是如何实现的,以便能够查询 数以百万计的条目非常快? 请注意:我不是谈论通过在空格处分隔内容来标记内容的系统,而是谈论能够 甚至查询令牌中间的部分(这是一个真正的挑战)。

背景信息
我尝试了一个自制的字符串缓存器(使用 Java),它能够搜索 对于字符串,给定一个子字符串作为查询。子字符串 不是 必需的 位于可能检索到的字符串的开头。

它适用于大量字符串。 使用 a
TreeMap<Character,TreeSet<String>> 完成缓存。

添加条目
对于待添加字符串中的每个唯一字符:
获取该字符的集合,并将字符串添加到其中。

示例:“test”首先拆分为“t”、“e”、“s”。
然后,我们检索这些集合 三个键,并将“测试”添加到每个集合中。

查询
查询是通过将查询拆分为唯一字符来完成的, 为每个字符检索一个Set<String>,建立一个交集 所有集合,最后使用contains()搜索交叉点以确保正确 查询字符的顺序。

基准测试
3GHz 机器上,我添加了 2'000'000 字符串 平均长度 共 10 个,随机内容。
完成 100 个查询。耗时:最小值:0.4 秒,平均值:0.5 秒,最大值:0.6 秒
1.5GB 内存被浪费了。

【问题讨论】:

    标签: java caching indexing full-text-search


    【解决方案1】:

    一种方法是存储文本所有尾部的排序排列(从特定点到结尾的文本)。

    然后要找到一个子字符串,您可以在这些循环移位中对其进行二进制搜索。使用 32 位整数使用的内存将是每个原始字符 4 个字节。

    p.s:我听说有一种方法可以通过存储文本的 Burrows-Wheeler transform(每个原始字符 1 个字符)来完成类似的事情,但我似乎找不到任何对它的引用..

    【讨论】:

    • 排列组合!好主意啊!我只是将每个“单词”拆分为字符,对它们进行排序,并将结果存储为映射键(这样的结果将是“初始排列”或“排列 0”)。查询也类似!
    • 哦,对不起,我的排列建议不允许搜索部分字符序列:(
    【解决方案2】:

    我实现了这样一个系统,其中一个建议使用 n-gram 索引,特别是 3-gram 在网站上进行下拉。您将一个单词拆分为它的组成 n-gram,例如对于单词“hello”,您将得到“hel”、“lo”。然后你建立一个索引,以 n-gram 作为键,它们来自的词作为值。 (为了速度,我使用了 trie,内存是一个较小的问题)。接下来,对于给定的查询,您通过与索引期间相同的过程将其分解为 n-gram,并对每个 n-gram 执行查找以获得可能匹配的列表。从该列表中,您选择匹配 n-gram 数量最多的单词。您还可以使用各种启发式方法。一个是单词开头的匹配通常更重要,因此您可以用 $ 填充所有单词。

    【讨论】:

      【解决方案3】:

      你可能想看看 Lucene。但我认为总的来说,它们确实对输入文本进行了标记。也许不仅仅是空格,还可以使用更短的字内序列。我认为单字符标记是不可行的。

      对于东方语言(没有空格),通常使用二元组,即两个字符序列。与英语的主要区别在于,两个字符通常已经是一个单词,并且要从中提取的基本字符集要大得多,因此二元组中已经有很多信息,并且独特的二元组要多得多。克。

      【讨论】:

        猜你喜欢
        • 2012-09-03
        • 2020-04-13
        • 2012-04-06
        • 2012-05-19
        • 1970-01-01
        • 2020-05-05
        • 2011-04-25
        • 2016-02-15
        • 2014-10-06
        相关资源
        最近更新 更多