【问题标题】:MySQL fulltext search over multiple columns does not deliver the expected resultsMySQL 对多列的全文搜索没有提供预期的结果
【发布时间】:2014-03-17 18:20:27
【问题描述】:

我有一个名为“上传”的表格。这些列是 id、date、last_update、description、tags。我添加了全文索引“description_tags”,其中包括那些列描述和标签。表格格式为 MyISAM。如果这可能是问题,我正在使用 USBWebserver。

现在我尝试选择其中包含提供的 GET 变量的上传。

MATCH (description,tags) AGAINST ("'.urldecode($_GET['tags']).'")

但是我得到的结果的问题是:当我搜索“lorem”时没有结果,但是当我在查询中添加 IN BOOLEAN MODE 时有一个结果。 “Lorem”实际上在描述列中。在标签列中搜索关键字没有这个问题。更有趣/更烦人的是,当我搜索同样在描述表中的“moree”时,我得到的结果有无布尔模式......

这里有什么问题?没看到。

更新

if ( $upload_display_sort == 'popular' )//sort by popularity

$query =    //select 'u' (a new defined variable?)
            'SELECT u.* '.
            //from the following table
            'FROM '.
            //uploads table as variable u
            'uploads u '.
            //join the following table
            'LEFT OUTER JOIN '.
            //select the column upload_id, count all columns into variable 'num' ???
            '(SELECT upload_id, COUNT(*) AS num '.
            //from the favorites table as variable f
            'FROM favorites f '.
            //and group it by the upload_id in the favorites table
            'GROUP BY upload_id) '.
            //what does this do? combine rows where the u.id == f.upload_id ???
            'f ON u.id = f.upload_id';

else $query = 'SELECT * FROM uploads';//select all from uploads



$query .=   ' WHERE online_state = 1';//select all online uploads



//FILTER FAVORITES

if  ($upload_display_sort == 'favorites' and !empty($favorites_ids))

$query .= ' AND id IN ('.implode(',', $favorites_ids).')';//returns 1,2,3,4,5

elseif  ($upload_display_sort == 'favorites' and empty($favorites_ids))

$query .= ' AND id IN (0)';//no upload id is 0



//FILTER SEARCH

if  (   isset($_GET['tags'])    )

$query .= ' AND MATCH (description,tags) AGAINST ("'.urldecode($_GET['tags']).'" IN BOOLEAN MODE)';



//FILTER DATE

if  (   isset($_GET['timeframe']    )

    and (   $_GET['timeframe'] == '3days'

        or  $_GET['timeframe'] == '2weeks'

        or  $_GET['timeframe'] == '3months')    )

{

    $end_date = time();//current time in unix format

    switch  (   $_GET['timeframe']  )

    {
        case '3days':   $start_date = strtotime('-3 days',$end_date);   break;
        case '2weeks':  $start_date = strtotime('-2 weeks',$end_date);  break;
        case '3months': $start_date = strtotime('-3 months',$end_date); break;
        default:        $start_date = strtotime('');    break;//1970-01-01 01:00:00
    }

    $end_date = date("Y-m-d H:i:s", $end_date);//current time in mysql format

    $start_date = date("Y-m-d H:i:s", $start_date);//end time in mysql format

    $query .= ' AND last_update BETWEEN "'.$start_date.'" AND "'.$end_date.'"';

}



//ORDER

$query .= ' ORDER BY';

if ( $upload_display_sort == 'popular' )//sort by popularity

$query .= ' f.num DESC,';

$query .= ' last_update DESC, id DESC';

【问题讨论】:

  • 实际查询是什么样子的,变量展开了?
  • 看起来像这样SELECT * FROM uploads WHERE MATCH (description,tags) AGAINST ("lorem")

标签: php mysql search full-text-search


【解决方案1】:

您的测试数据可能不完整。请注意docs 中的以下内容:

考虑出现在 50% 或更多行中的单词 常见且不匹配。

然而BOOLEAN MODE searches 的不同之处在于:

他们不使用 50% 的阈值。

我猜“lorem”出现在 50% 或更多的行中。

BOOLEAN MODE 全文搜索不会通过降低相关性来自动排序。您需要像这样自己对它们进行排序:

SELECT *, MATCH (description,tags) AGAINST ("lorem") AS relevance
FROM uploads
WHERE MATCH (description,tags) AGAINST ("lorem" IN BOOLEAN MODE)
ORDER BY relevance DESC

【讨论】:

  • 因为我不希望任何单词是“常见的”并从搜索中排除,我想我必须使用 BOOLEAN MODE。我实际上尝试在一行中添加“amet”并且它正在被发现 - 所以我想这是因为你提到的 50% 的事情。但我只是编辑了一些虚拟上传条目。我在他们的描述中添加了“四”和“七”。搜索它们时,两者都不会成为结果。描述和搜索的作品中存在艰难的“好”。是否存在未搜索/排除关键字之类的问题?
  • @handle,是的,有stop words 的列表。 “四”和“七”都在里面。如果这是您的服务器,您可以configure that list。如果它是共享服务器(共享主机),您可能无法使用。
  • 我无法更改它们 - 它是共享主机 - 我想我可以不用这些词。但是我刚刚读到的关于布尔模式搜索的内容:它们不会自动按照相关性递减的顺序对行进行排序。相关性最高的行是包含两次“MySQL”的行,但它被列在最后,而不是第一个。我宁愿反过来。我可以使用非布尔搜索并删除 50% 的常用词排除吗?或者反转布尔搜索结果?
  • @handle,布尔全文搜索不会自动按相关性对结果进行排序。请参阅我更新的解决方案答案,但我不确定相关性分数在 BOOLEAN 模式下的准确度。
  • 好的,如果这可行,那就太好了,但实际上我已经有了这个复杂的大查询:) 我不知道我是如何得到它的。我可以简单地在其中添加底部的东西(WHERE MATCH(描述,标签)反对(“lorem”)ORDER BY相关性DESC)。但我不确定我是如何在您建议的 SELECT 部分中输入的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-06
  • 2012-06-13
  • 1970-01-01
  • 2018-05-19
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
相关资源
最近更新 更多