【问题标题】:Searching a database with forgiveness.宽恕地搜索数据库。
【发布时间】:2012-07-10 07:00:34
【问题描述】:

我有一个包含 30k 个元素的数据库,每个游戏名称。

我目前正在使用:

SELECT * from gamelist WHERE name LIKE '%%%$search%%%' OR aliases LIKE '%$search%' LIMIT 10"

用于搜索栏。
但是,它可能对以下内容非常挑剔:

'Animal Crossing: Wild World' 

你看,很多用户不知道':'在那个短语中,所以当他们开始搜索时:

 Animal Crossing Wild World 

它不会出现。

我怎样才能让 sql 更宽容?

【问题讨论】:

标签: php sql search


【解决方案1】:

将搜索参数中的非字母数字字符替换为通配符,使Animal Crossing Wild World 变为%Animal%Crossing%Wild%World% 并对其进行过滤。

【讨论】:

  • 我认为这更像是我知道我需要的解决方案,我只是想找到最好的方法来做到这一点。
  • 关于全文的其他解决方案可能是一个更好的主意,但我认为这个答案更准确地解决了我的特定问题,也是一个非常简单的解决方案:preg_replace("/[^A-Za-z0-9]/", '%', $search);
【解决方案2】:

我建议你制作另一个包含类似钥匙的桌子

+---------+------------+
| game_id | keyword_id |
+---------+------------+
|       1 |          1 |
|       1 |          2 |
|       1 |          3 |
|       1 |          4 |
+---------+------------+

 

+------------+--------------+
| keyword_id | keyword_name |
+------------+--------------+
|          1 | animal       |
|          2 | crossing     |
|          3 | wild         |
|          4 | world        |
+------------+--------------+

之后,您可以轻松地将用户给定的文本分解为关键字并在数据库中搜索它们,witch 会为您提供他/她正在寻找的可能游戏的 ID。

哦,去掉特殊符号,比如“:”或“-”,这样你就不需要为同一个词组使用多个关键字了。

【讨论】:

  • 这个想法不错,但您最终会多次使用相同的关键字:每个匹配的 game_id 一个。也许是关键字的表:Keyword(keyword_id, keyword) 和进行匹配的表:GameKeyword(game_id, keyword_id)
  • 没错,把答案改成了你的想法。
【解决方案3】:

以下内容来自MySQL LIKE %string% not quite forgiving enough. Anything else I can use?用户M_M:

如果您使用的是 MyISAM,则可以使用全文索引。 See this tutorial

如果您使用不同的存储引擎,您可以使用像 sphinx 这样的第三方全文引擎,它可以充当storage engine for mysql 或可以查询的单独服务器。

使用 MySQL 全文索引,在 A J Kelly 上的搜索将匹配 AJ Kelly(不会混淆,但 A、J 和 AJ 将被忽略,因为默认情况下它们太短,它会匹配 Kelly。)一般全文更宽容(通常比 LIKE '%string%' 更快),因为允许部分匹配,然后可以根据相关性进行排名。

您还可以使用SOUNDEX 为单词的发音等价物编制索引,并通过在您的搜索词上应用 SOUNDEX 然后使用它们来搜索索引来搜索它们,从而使搜索更加宽容。例如,soundex marymariemarry 将全部匹配。

【讨论】:

  • 我以前使用过 SOUNDEX,但这些结果也没有产生正确的结果。除非我用错了:SELECT * from gamelist WHERE SOUNDEX(name) = SOUNDEX('%%%$search%%%') OR SOUNDEX(aliases) = SOUNDEX('%$search%') LIMIT 10
  • 恐怕我以前从未真正使用过 SOUNDEX(正如我在回答中所说,引用来自用户 M_M),所以我无法验证您查询的有效性。跨度>
【解决方案4】:

如果您的 MySQL 引擎是 MyISAM 或 InnoDB,您可以尝试 Match () AGAINST ():

http://dev.mysql.com/doc/refman/5.6/en/fulltext-search.html

http://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html

生成的 SQL 将如下所示:

SELECT * from gamelist WHERE MATCH (name, aliases) AGAINST ('$search' IN BOOLEAN MODE) LIMIT 10

搜索的行为更像是搜索引擎中使用的布尔搜索。

【讨论】:

  • 我没有为这些表格使用全文。
  • @Adola 如果您碰巧使用的是 MyISAM,那么实际上不需要全文索引即可使用 IN BOOLEAN MODE 搜索。不幸的是,InnoDB 需要它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
相关资源
最近更新 更多