我想知道,如何实现全文搜索系统,以便能够查询 数以百万计的条目非常快? 请注意:我不谈论通过在空白处分隔内容来标记内容的系统,而是关于能够对系统进行分类的系统 甚至可以从令牌中间查询部分(这是一个真正的挑战)。
背景资料
我尝试了一个能够搜索的自制字符串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 的内存被浪费了。
答案 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。但我认为一般来说,它们会对输入文本进行标记。也许不只是通过空格,而是使用更短的词内序列。我不认为单字符令牌是可行的。
对于东方语言(没有空格),经常使用双字节,即双字符序列。与英语的主要区别在于两个字符通常已经是一个单词,并且要绘制的基本字符集要大得多,因此二进制文件中已经存在大量信息,并且还有更多独特的双字符。克。