是否有一种有效的算法来执行反向全文搜索?

时间:2011-08-17 04:20:46

标签: algorithm search

我在数据库中有数千个关键字(每个关键字中包含一个或多个单词)的有限列表。我想有效地找到哪些关键字在给定的输入文本中,而不必逐个测试每个关键字(全表扫描)。允许匹配文本中的一些拼写错误的单词会更好但不是必需的。任何算法/文章建议来解决这个问题?

6 个答案:

答案 0 :(得分:4)

我认为到目前为止,一些答案误解了所提出的问题。我的理解是你有一个(大的)单词列表和一个(大的)文本正文。你想知道两个列表中哪些词有共同之处,这是正确的吗?

如果是这样,这根本不是一个全文问题。基本上,您只有两个单词列表(原始关键字和输入文本中的单词列表)。如果对两个列表进行排序,则可以同时扫描两个列表并提取共同的单词。

假设关键字列表已经排序,您可以在O(n logn)时间内从文本正文中提取和排序单词,然后同时扫描两个列表是O(n + m)(其中n是文本正文中的单词数和m是关键字列表中的单词数。)

答案 1 :(得分:1)

我不知道您使用的是哪个数据库但知道如果是Oracle,您应该可以访问Oracle Text功能(或者您可以请求您的DBA启用它)。借助CONTAINS等其他功能以及Oracle Text索引的正确使用,您可以实现您想要的功能,甚至可以查找“拼写错误”的单词。这是通过将CONTAINS与计算两个字符串之间的Levenshtein distance的函数相结合来完成的。在Oracle Text中,此函数为FUZZY

在这个Oracle documentation中有一个完美的例子。

我不太了解其他类型的数据库,但我很确定主要供应商确实有适当的搜索文本。只需快速搜索,即可进行全文搜索:

无论如何,使用内置的DBMS函数/过程要快得多,而不是创建自己的自定义函数,甚至用你的编程语言进行搜索(虽然成千上万的关键字并不是那么多)

编辑:再次阅读你的问题后,Dean Harding的回答我觉得我没有正确回答这个问题。使用Oracle Text,而不是使用CONTAINS函数,您可以使用MATCHES函数(请参阅Paragraph 4.1.3),它完全相同:查询存储在表中的关键字列表并返回找到的关键字的ID。我将在下面复制文档中的示例(添加了我自己的评论):

create table queries (
  query_id      number,
  query_string  varchar2(80)
);

// Here we populate the table with the keywords
insert into queries values (1, 'oracle');
insert into queries values (2, 'larry or ellison');
insert into queries values (3, 'oracle and text');
insert into queries values (4, 'market share');

create index queryx on queries(query_string)
  indextype is ctxsys.ctxrule;

// This query will return the ids of the matched keywords
select query_id from queries
 where matches(query_string, 
               'Oracle announced that its market share in databases 
                increased over the last year.')>0

我希望它比我的第一次尝试更有帮助。

Edit2:只是为了添加你不使用这种方法执行全表扫描,因为你正在使用域索引。

答案 2 :(得分:1)

您可以使用Apache LuceneApache Solr(基于Lucene的HTTP全文服务)等解决方案来实现此目标。

Apache Lucene提供了一个API来索引您想象的任何数据。

根据您的需求,您可以选择其中一种:

  • Lucene:索引嵌入您的应用程序。此外,Lucene还提供文件系统索引存储或内存。 此外,一个重要的考虑因素是Lucene并未在所有编程语言中实现
  • Solr:集中索引服务。如果您需要以分布式方式访问此信息,Solr是您的最佳选择。此外,它提供了Lucene硬概念的一些抽象,使其易于使用。 由于使用HTTP协议和XML在点之间交换信息,这是异构平台之间最好的解决方案

关于拼写检查功能,Solr包含使用built-in component

的拼写检查“建议”

一些教程/信息:

  • Solr:Wiki是您需要的唯一资源。
  • Lucene:在StackOverflow中,您可以找到有关教程的问题,例如this

答案 3 :(得分:1)

您可以使用所描述的任何给定解决方案,但它们从根本上做同样的事情(然后添加铃声和口哨声)

所以基本方法是:

  1. 将搜索输入拆分为单词
  2. 去除噪音(这可能是非常常见的词,标点符号等)
  3. 您的数据库应该包含您的关键短语(您说关键字可能有多个单词,所以 它的关键词)
  4. 您有关键短语中的字词地图
  5. e.g。

    keyphraseID:1个关键词:“快速的棕色狐狸”

    wordID:1字:

    wordID:2 Word:quick

    mapID:1 keyphraseID:1 wordID:1位置:1

    mapID:2 keyphraseID:1 wordID:2 position:2

    现在你有一个基本的逆索引,并且通过在单词列上放置一个唯一索引 - 你可以避免全表扫描。

    模糊/拼写调整可以通过包括诸如Levenshtein距离,soundex或潜在语义索引之类的东西来添加 - 很大程度上取决于你正在做什么,有很多研究可用于此。

    编辑: -

    您还可以查看词干 - 您将文字带回同一个词根,例如修复并修复了“修复”中的两个根。常见的词干算法称为porter。

答案 4 :(得分:0)

正确的方法是建立一个自动机。

Automaton(根据定义)用于识别语言的单词,在本例中是您的关键词集合。

当然,在你的情况下,它有点复杂,因为你可能有重叠的关键字,但它也没有那么不同。

所以,从纯理论的角度来看:

  • 根据您的关键字构建自动机
  • 感谢自动机
  • 扫描文本正文

后者是O(n),前者可能有点棘手。

答案 5 :(得分:0)

在互联网上搜索Aho-Corasick算法。