全文索引器(或缓存)如何工作?

时间:2009-06-17 22:40:15

标签: java caching indexing full-text-search

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

背景资料
我尝试了一个能够搜索的自制字符串cacher(使用Java) 对于字符串,给定子字符串作为查询。子字符串不是 处于潜在检索字符串的开头。

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

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

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

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

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

3 个答案:

答案 0 :(得分:1)

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

然后找到一个子字符串,在那些循环移位中二进制搜索它。使用32位整数的内存将是每个原始字符4个字节。

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

你可能想看看Lucene。但我认为一般来说,它们会对输入文本进行标记。也许不只是通过空格,而是使用更短的词内序列。我不认为单字符令牌是可行的。

对于东方语言(没有空格),经常使用双字节,即双字符序列。与英语的主要区别在于两个字符通常已经是一个单词,并且要绘制的基本字符集要大得多,因此二进制文件中已经存在大量信息,并且还有更多独特的双字符。克。