【问题标题】:Good algorithm for searching DB for a given string为给定字符串搜索数据库的好算法
【发布时间】:2015-04-06 08:14:55
【问题描述】:

我正在开发一个网络应用程序(PHP + MySQL),用户可以通过输入一些搜索字符串来搜索其他用户。

我需要将用户的输入字符串与数据库中“用户”表的 2 列(用户名和全名)相匹配,并返回最相关的(20 或 50 个)匹配项。理想情况下,我还需要考虑拼写错误。

我该如何处理?我不想在这里重新发明轮子。

【问题讨论】:

  • 如今,人们通常将 Elastic Search 和 Apache Solr 等技术用于此类事情(您已经在谈论搜索结果相关性)。我知道这是您堆栈中的另一件事,但对您来说不那么令人头疼。

标签: mysql database search text


【解决方案1】:

您可以使用MySQL full Text search

请查看thisthisthis 的文章。

我想给你解释一下Boolean Full Text Search;但我建议你也请通过Full Text Search using Query Expansion

让我们看看 dev.mysql.com 上给出的示例表:

mysql> select * from articles;
+----+-----------------------+------------------------------------------+
| id | title                 | body                                     |
+----+-----------------------+------------------------------------------+
|  1 | PostgreSQL Tutorial   | DBMS stands for DataBase ...             |
|  2 | How To Use MySQL Well | After you went through a ...             |
|  3 | Optimizing MySQL      | In this tutorial we will show ...        |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ...      |
|  5 | MySQL vs. YourSQL     | In the following database comparison ... |
|  6 | MySQL Security        | When configured properly, MySQL ...      |
+----+-----------------------+------------------------------------------+

mysql> SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('"database comparison"' IN BOOLEAN MODE);

+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+

顺序很重要,引用的话:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('"comparison database"' IN BOOLEAN MODE);

Empty set (0.01 sec)

当我们删除引号时,它会搜索包含单词“database”或“comparison”的行:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('database comparison' IN BOOLEAN MODE);

+----+---------------------+------------------------------------------+
| id | title               | body                                     |
+----+---------------------+------------------------------------------+
|  1 | PostgreSQL Tutorial | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL   | In the following database comparison ... |
+----+---------------------+------------------------------------------+

现在订单无关紧要:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('comparison database' IN BOOLEAN MODE);

+----+---------------------+------------------------------------------+
| id | title               | body                                     |
+----+---------------------+------------------------------------------+
|  1 | PostgreSQL Tutorial | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL   | In the following database comparison ... |
+----+---------------------+------------------------------------------+

如果我们想要获取包含单词“PostgreSQL”或短语“数据库比较”的行,我们应该使用这个请求:

mysql> SELECT * FROM articles WHERE MATCH (title,body)
     AGAINST ('PostgreSQL "database comparison"' IN BOOLEAN MODE);

+----+---------------------+------------------------------------------+
| id | title               | body                                     |
+----+---------------------+------------------------------------------+
|  1 | PostgreSQL Tutorial | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL   | In the following database comparison ... |
+----+---------------------+------------------------------------------+

Fiddle To Try

确保您要搜索的字词不在list of stopwords 中,这些字词将被忽略。
(显然,像'is','the'这样的词是stopwords,而那些被忽略了)

要在布尔模式下增强对结果的排序,您可以使用以下查询:

(假设您在用户的输入字符串中总共有 2 个单词)然后。

SELECT column_names, MATCH (text) AGAINST ('word1 word2')
AS col1 FROM table1
WHERE MATCH (text) AGAINST ('+word1 +word2' in boolean mode) 
order by col1 desc;

(如果用户输入的字符串中有 3 个单词)那么..

SELECT column_names, MATCH (text) AGAINST ('word1 word2 word3')
AS col1 FROM table1
WHERE MATCH (text) AGAINST ('+word1 +word2 +word3' in boolean mode) 
order by col1 desc;

使用first MATCH() 我们在非布尔搜索模式下获得分数(更具特色)第二个 MATCH() 确保我们只返回我们想要的结果(全部三个字)

【讨论】:

    【解决方案2】:

    我会在两列中进行类似搜索

    我的查询会是这样的

    select * from (select * from user where (username like ='%{input}%' or lastName like '%{input}%')) and rownum =20

    您需要编写一个自定义清理算法来清理您输入的拼写错误

    【讨论】:

    • 我需要一个更复杂的解决方案@Balaji
    • @Balaji, Joseph 提到了最相关的匹配项。这只是典型的搜索
    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多