【问题标题】:Whats the easiest site search application to implement, that supports fuzzy searching?支持模糊搜索的最简单的站点搜索应用程序是什么?
【发布时间】:2010-12-26 08:21:45
【问题描述】:

我有一个网站需要搜索大约 20-30k 条记录,其中大部分是电影和电视节目名称。该站点使用 memcache 运行 php/mysql。

我希望将FULLTEXT 替换为我目前拥有的soundex() 搜索,这可行……有点,但在许多情况下并不是很好。

是否有任何体面的搜索脚本易于实现,并且将提供体面的搜索功能(表中的 3 列)。

【问题讨论】:

    标签: php mysql search fuzzy-search


    【解决方案1】:

    ewemli 的答案是正确的,但您应该结合 FULLTEXT 和 soundex 映射,而不是替换全文,否则您的 LIKE 查询可能会很慢。

    create table with_soundex (
      id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
      original TEXT,
      soundex TEXT,
      FULLTEXT (soundex)
    );
    
    insert into with_soundex (original, soundex) values 
    
    ('add some test cases', CONCAT_WS(' ', soundex('add'), soundex('some'), soundex('test'), soundex('cases'))),
    ('this is some text', CONCAT_WS(' ', soundex('this'), soundex('is'), soundex('some'), soundex('text'))),
    ('one more test case', CONCAT_WS(' ', soundex('one'), soundex('more'), soundex('test'), soundex('case'))),
    ('just filling the index', CONCAT_WS(' ', soundex('just'), soundex('filling'), soundex('the'), soundex('index'))),
    ('need one more example', CONCAT_WS(' ', soundex('need'), soundex('one'), soundex('more'), soundex('example'))),
    ('seems to need more', CONCAT_WS(' ', soundex('seems'), soundex('to'), soundex('need'), soundex('more')))
    ('some helpful cases to consider', CONCAT_WS(' ', soundex('some'), soundex('helpful'), soundex('cases'), soundex('to'), soundex('consider')))
    
    select * from with_soundex where match(soundex) against (soundex('test'));
    +----+---------------------+---------------------+
    | id | original            | soundex             |
    +----+---------------------+---------------------+
    |  1 | add some test cases | A300 S500 T230 C000 | 
    |  2 | this is some text   | T200 I200 S500 T230 | 
    |  3 | one more test case  | O500 M600 T230 C000 | 
    +----+---------------------+---------------------+
    
    select * from with_soundex where match(soundex) against (CONCAT_WS(' ', soundex('test'), soundex('some')));
    +----+--------------------------------+---------------------------+
    | id | original                       | soundex                   |
    +----+--------------------------------+---------------------------+
    |  1 | add some test cases            | A300 S500 T230 C000       | 
    |  2 | this is some text              | T200 I200 S500 T230       | 
    |  3 | one more test case             | O500 M600 T230 C000       | 
    |  7 | some helpful cases to consider | S500 H414 C000 T000 C5236 | 
    +----+--------------------------------+---------------------------+
    

    这提供了非常好的结果(在 soundex 算法的范围内),同时最大限度地利用了索引(任何查询 LIKE '%foo' 都必须扫描表中的每一行)。

    注意对每个单词而不是整个短语运行 soundex 的重要性。您也可以在每个单词上运行自己的 soundex 版本,而不是让 SQL 来做,但在这种情况下,请确保在存储和检索时都这样做,以防算法之间存在差异(例如,MySQL 的算法不限制本身符合标准4 chars)

    【讨论】:

      【解决方案2】:

      如果您正在寻找一个简单的现有解决方案而不是创建自己的解决方案,请查看

      【讨论】:

        【解决方案3】:

        mysql中有一个函数SOUNDEX。如果您想搜索电影名称:

        select * from movie where soundex(title) = soundex( 'the title' );
        

        当然不能在文本中搜索,例如电影或情节摘要。


        Soundex 是一个比较简单的algo。您也可以决定在应用级别处理所有这些,这可能更容易:

        • 存储文本时,对其进行标记并将 soundex 应用于所有单词
        • 将原始文本和 soundex 版本存储在两列中
        • 搜索时,在应用程序中计算 soundex。级别,然后在 db 级别使用常规 LIKE

        【讨论】:

        • 我很感兴趣。如果 film.title 是“Apocalypse Now”但用户搜索“Apocalypse Cow”,那么 soundex 很可能会找到匹配项 '... where film.title="$user_title" OR soundex(film.title) = soundex( $用户标题)';但这在包含“Martin Sheen”并且用户搜索“Martin Shean”的film.intro var(255)中不起作用,我明白了吗?抱歉,如果此 Q/评论发错地方,请纠正我。
        • soundex('马丁·辛的电影') -> A513563525, select soundex('A'), soundex('movie'), soundex('with'), soundex('Martin') ,soundex('光泽'); --> A000, M100, W300, M635, S500 因此,如果您存储文本 'A000 M100 W300 M635 S500' 的 soundex 版本并使用 LIKE '%M635%S500%' 搜索可能没问题。然而,这仍然不是最优的。搜索 'Mart Insheen'(可能对名称有误解)会产生 LIKE "%M630%I525%' 并且不起作用。
        【解决方案4】:

        Soundex 在处理模糊搜索方面存在局限性。一个更好的功能是编辑距离,可以使用UDF集成到MySQL中。检查 http://flamingo.ics.uci.edu/toolkit/ 以获取 Linux 上 MySQL 的 C++ 实现。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-09-08
          • 2012-09-17
          • 1970-01-01
          • 1970-01-01
          • 2011-11-07
          相关资源
          最近更新 更多