如何实现有效的连续单词搜索?

时间:2010-10-07 20:43:59

标签: algorithm database-design search

搜索引擎和数据库允许您使用与"this is a test"匹配但与this is a test that will match不匹配的连续字符串搜索(例如test this is a)。

我知道有些数据库具有内置功能,允许您使用相同的功能而无需编写任何代码(例如MySQL的全文搜索)。那不是我要找的那种答案。

我想知道的是使用什么样的算法和数据库结构来快速搜索字符串。

鉴于以上示例,索引表的外观如何?它会与此类似吗?

// IndexedItemID | Position | Word
1 | 0 | this
1 | 1 | is
1 | 2 | a
1 | 3 | test
1 | 4 | that
1 | 5 | will
1 | 6 | match
2 | 0 | test
2 | 1 | this
2 | 2 | is
2 | 3 | a

既然存在索引项,那么如何有效地创建与这些项匹配的SQL语句呢?

以下是我能想到的一个例子:

select IndexedItemID form
  (select IndexedItemID, Position from indexedWords where Word = "this") as word1Position
where
  exists(select * from indexedWords where IndexedItemID = word1Position.IndexedItemID AND Word = "is" AND Position = word1Position.Position + 1)
  AND exists(select * from indexedWords where IndexedItemID = word1Position.IndexedItemID AND Word = "a" AND Position = word1Position.Position + 2)
  AND exists(select * from indexedWords where IndexedItemID = word1Position.IndexedItemID AND Word = "test" AND Position = word1Position.Position + 3)

我确信可能有更标准化的方式更有效率。

3 个答案:

答案 0 :(得分:1)

您可能希望查看Trie。它们在这样的场景中非常有效,但是消耗大量内存来存储整个结构。

答案 1 :(得分:1)

您想要的是从文档中对单词的反向索引进行排序。基本上如果你的文字是

“这是一个例句。这就是你如何编制索引”你把它变成:

Here: 1
is: 2, 7
an: 3
example: 4
......
......

然后,当您搜索单词序列时,查找每个单词的位置列表。现在,您希望同时遍历已排序位置列表,就像您尝试合并列表一样。在合并列表的同时,很容易发现单词列表按照您希望的顺序出现的任何位置。

答案 2 :(得分:0)

我不确定sql数据库如何缩小搜索范围,但最终会归结为字符串匹配。

当你有一个目标字符串和一个模式字符串时,最简单的比较方法是从目标字符串的开头开始,并尝试将它与逐个字符的模式字符串匹配。如果匹配失败,则前进到目标字符串中的下一个字符并重复上述步骤。这显然是低效的,因为复杂度是O(m * n)的顺序,其中m是模式字符串中的字符数,n是目标字符串中的字符数。

有一种名为Rabin-Karp algorithm的算法可以使用散列在O(m + n)中执行此搜索。

当然,mysql可以计算出有助于减少目标字符串数量的哈希值。