1

我有下表:

CREATE TABLE IF NOT EXISTS `search`
(
    `id` BIGINT(16) NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `string` TEXT NOT NULL,
    `views` BIGINT(16) NOT NULL,
    FULLTEXT(string)
) ENGINE=MyISAM;

它共有 5,395,939 个条目。要对某个词(如“a”)执行搜索,我使用以下查询:

SELECT * FROM `search` WHERE MATCH(string) AGAINST('+a*' IN BOOLEAN MODE) ORDER BY `views` DESC LIMIT 10

但是真的很慢=(。上面的查询用了15.4423秒执行。显然,不用排序就快了views,不到0.002s。

我正在使用 ft_min_word_len=1 和 ft_stopword_file=

有没有办法在全文搜索中使用视图作为相关性,而不会让它太慢?例如,我希望搜索词“a b”匹配“big apple”,而不是“ibg apple”(只需要匹配搜索前缀)。

谢谢

4

1 回答 1

0

由于没有人回答我的问题,我发布了我的解决方案(不是我希望看到的我是否在谷歌搜索的解决方案,因为它不像简单的数据库设计那样容易应用,但它仍然是一个解决方案到这个问题)。我无法用 MySQL 使用的任何引擎或函数真正解决它。对不起=/。

所以,我决定开发自己的软件来做这件事(用 C++,但你可以用任何其他语言应用它)。如果您要寻找的是一种在小字符串中搜索某些单词前缀的方法(我的字符串的平均长度是15),那么您可以使用以下算法:

1. Create a trie. Each word of each string is put on the trie.
   Each leaf has a list of the ids that match that word.
2. Use a map/dictionary (or an array) to memorize the informations
   for each id (map[id] = information).

搜索字符串: 注意:字符串的格式为“word1 word2 word3...”。如果它有一些符号,如#、@、$,您可能会将它们视为“”(空格)。示例:“拉斐尔·佩雷拉”

1. Search for the prefix "Rafael" in the trie. Put all the ids you
   get in a set (a Binary-Search Tree that ignores repeated values).
   Let's call this set "mainSet".
2. Search for the prefix "Perrella" in the trie. For each result,
   put them in a second set (secSet) if and only if they are already
   in the mainSet. Then, clear mainSet and do mainSet = secSet.
3. IF there are still words lefting to search, repeat the second step
   for all those words.

在这些步骤之后,您将拥有一个包含所有结果的集合。使用 (views, id) 对创建一个向量,并按降序对向量进行排序。所以,只要得到你想要的结果......我限制了 30 个结果。

注意:您可以先对单词进行排序以删除具有相同前缀的单词(例如,在“Jan Ja Jan Ra”中您只需要“Jan Ra”)。我不会解释它,因为算法很明显。

这种算法有时可能很糟糕(例如,如果我搜索“abcdef ... z”,我将搜索整个 trie...)。所以,我做了一个改进。

1. For each "id" in your map, create also a small trie, that will
   contain the words of the string (include a trie for each m[id]...
   m[id].trie?).

然后,进行搜索:

1. Choose the longest word in the search string (it's not guaranteed,
   but it is probably the word with the fewest results in the trie...).
2. Apply the step 1 of the old algorithm.
3. Make a vector with the ids in the mainSet.
4. Let's make the final vector. For each id in the vector you've created
   in step 3, search in the trie of this id (m[id].trie?) for all words
   in the search string. If it includes all words, it's a valid id and
   you might include it in the final vector; else, just ignore this id.
5. Repeat step 4 until there are no more ids to verify. After that, just
   sort the final vector for <views, id>.

现在,我将数据库用作轻松存储和加载数据的一种方式。该表中的所有查询都直接向该软件询问。当我添加或删除记录时,我会同时发送到数据库和软件,所以我总是保持更新。加载所有数据大约需要 30 秒,但是查询很快(最慢的查询为 0.03 秒,平均为 0.001 秒;使用我自己的笔记本,没有在专用主机中尝试过,可能很多快点)。

于 2013-01-06T21:11:42.613 回答