需要一些帮助(搜索算法)

时间:2012-10-26 11:06:00

标签: database algorithm search

我在这个问题上需要一些帮助:

作为输入,我有一个字符串,看起来像Blue cat green eyes 2342342,或者它可以是Cat blue eyes green 23242或任何其他字的排列。

在我的数据库表中,我有一些数据。其中一个专栏叫做keyWords。

以下是此表的示例:

enter image description here

我的任务是在我的数据库表格列KEYWORDS中找到记录,该列匹配输入字符串中的某些单词。

例如:对于字符串蓝猫绿眼睛2342342” 猫蓝眼睛绿色23242” 23242眼睛蓝色绿色”结果必须是“蓝猫”(我桌子的第一行)。 我能想象如何解决这个任务的唯一方法是:

  1. 始终从字符串中取出每个字。
  2. 在表格列中使用%like%搜索每个单词。
  3. 如果没有找到,则表示这个词不是关键,我们对它没兴趣。
  4. 如果发现一次 - 很棒!毫无疑问,这正是我们正在寻找的。
  5. 如果有多个结果:
  6. 来自字符串中的所有单词,这些单词未经过测试,但始终采用每个单词。
  7. 在步骤2的结果中使用%like%搜索此单词。
  8. 等...
  9. 此算法的图形架构为here

    但是如果表中有很多记录并且我的输入字符串包含大量单词,那么看起来这个算法的工作速度会很慢。

    所以,我的问题是:是否有任何特殊的算法可以帮助解决这个问题?

2 个答案:

答案 0 :(得分:4)

您可以采用其他表格,例如

ID    KeywordID     Word
1     1             blue
2     2             blue
3     1             cat

并转换字符串

"Blue cat green eyes 2342342"

在一系列索引和计数中:

SELECT KeywordID, COUNT(*) FROM ancillary WHERE Word IN ('blue','cat','green','eyes'...)

这将执行一系列完全匹配并返回,例如

KeywordID   Count
1           2
2           1

然后您知道ID为1的关键字组有两个单词,这意味着计数为2的所有单词都匹配。所以关键字1是满意的。第2组还有两个单词(黑色,猫),但只找到一个,但匹配在那里但不完整。

如果您还将关键字集大小与关键字ID一起记录,那么来自同一ID的所有关键字都将具有相同的KeywordSize,您也可以将它设为GROUP BY:

KeywordID   KeywordSize    Count
1           2              2
2           2              1

甚至可以SELECT COUNT(*)/KeywordSize AS match ... ORDER BY match并按相关性排序关键字匹配。

当然,一旦你有KeywordID,你可以在关键字表中找到它。

实施

您想要将关键字列表“black angry cat”添加到现有表格中。

因此,您将此关键字列表分解为单词:并获取“黑色”,“愤怒”和“猫”。

您通常会在已有的表中插入关键字列表,并检索新创建的行的ID,假设它是1701。

现在,您将这些单词插入到我们称之为“辅助”的新表中。此表仅包含主表的关键字行ID,单个单词以及该单词所来自的单词列表的大小。

我们知道我们总共插入3个单词,表格行1701,所以size = 3,我们插入这些元组:

(1701, 3, 'black')
(1701, 3, 'cat')
(1701, 3, 'angry')

(这些将获得他们自己的唯一ID,但这与我们无关。)

现在一段时间后我们会收到一句话,

'Schroedinger cat is black and angry'

我们可以首先针对要删除的空字列表运行查询,例如“is”和“and”。但这不是必要的。

然后我们可以运行与单词一样多的查询,从而发现没有任何行包含“Schroedinger”,我们可以放弃它。但这也没必要。

最后,我们针对辅助构建真正的查询:

SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
    FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
    GROUP BY KeywordID;

WHERE会返回这些行:

(1234, 'black') -- from 'black cat'
(1234, 'cat')   -- from 'black cat'
(1423, 'angry') -- from 'angry birds'
(1701, 'cat')   -- from 'black angry cat'
(1701, 'angry') -- from 'black angry cat'
(1701, 'black') -- from 'black angry cat'
(1999, 'cat')   -- from 'nice white cat'

因此,GROUP将返回这些行的KeywordID及其基数:

1423   1   50%
1701   3  100%
1234   2  100%
1999   1   33%

现在你可以通过匹配比率降序排序,然后按列表大小降序排序(因为匹配3个单词的100%优于匹配2的100%,匹配1合2比3匹配2更好): / p>

1701   3  100% -- our best match
1234   2  100% -- second runner
1423   1   50%
1999   1   33%

您还可以在一个查询中检索第一个表格,并添加匹配率:

SELECT mytable.*, total, match FROM
mytable JOIN (
SELECT KeywordID, COUNT(*) AS total, ListSize*100/COUNT(*) AS match
    FROM ancillary WHERE Word IN ('Schroedinger','cat','is','black','and','angry')
    GROUP BY KeywordID
) AS ancil ON (mytable.KeywordID = ancil.KeywordID)
ORDER BY match DESC, total DESC;

最大的成本是“辅助”中的完全匹配,必须在Word列上编制索引。

答案 1 :(得分:1)

你可能想看看全文搜索引擎,比如sphinx:http://sphinxsearch.com/

或者,另一种方法 - 创建存储过程,使用指定的分隔符将搜索字符串拆分为关键字,并查找数据库列中每个关键字的charindex(取决于您的数据库管理系统)