在WHERE子句中使用FULLTEXT搜索的相关性分数

时间:2016-03-06 17:49:28

标签: mysql sql

我有一个简单的全文搜索查询:

SELECT *, MATCH(col1,col2,col3) AGAINST ('keywords' IN BOOLEAN MODE) AS relev FROM table1 WHERE relev > 0 ORDER BY relev DESC

技术上有效,但它也返回相关性为0的结果。

我试图使用:

relev

但这告诉我relev是无效的列名。

有没有办法排除MATCH(..) AGAINST(..)为0的结果,而不必在WHERE子句中再次使用{{1}}?不这样做基本上再次重复全文搜索并花费两倍的时间吗?

2 个答案:

答案 0 :(得分:1)

您可以改为使用having子句:

SELECT t.*,
       MATCH(col1, col2, col3) AGAINST ('keywords' IN BOOLEAN MODE) AS relev
FROM table1 t
HAVING relev > 0
ORDER BY relev DESC;

SQL(通常)不允许在WHERE子句中使用列别名。但是,MySQL会在HAVING子句中允许它们(并非所有数据库都这样)。这对于这种情况很方便。

答案 1 :(得分:0)

The MySql docs 暗示使用 HAVING 将导致仅在评估所有相关性分数后进行过滤。

<块引用>

HAVING 子句几乎最后应用,就在项目被发送到客户端之前,没有优化。 (LIMIT 在 HAVING 之后应用。)

<块引用>

不要对应该在 WHERE 子句中的项目使用 HAVING。

重复MATCH() is actually better

的表现 <块引用>

要实现此结果,您应该指定 MATCH() 两次:一次在 SELECT 列表中,一次在 WHERE 子句中。这不会导致额外的开销,因为 MySQL 优化器注意到两个 MATCH() 调用是相同的,并且只调用一次全文搜索代码。

我的实验和 this other StackOverflow QA 证实了这一点。

我也尝试使用内部查询

SELECT * FROM ( 
  SELECT textColumn, MATCH(textColumn) AGAINST('searchWord' IN BOOLEAN MODE) as relevance
  FROM table
)
WHERE relevance > 0

其性能与 HAVING 版本一样差。

我希望有一个替代方案的原因不是在查询中重复我自己 - DRY。

不幸的是,我认为不可能在没有性能损失的情况下避免重复自己,所以最后我选择了双 MATCH() AGGAINST()