MySQL全文搜索和按相关性+ TIME排序

时间:2015-02-19 20:49:45

标签: mysql sql sorting full-text-search full-text-indexing

我正在尝试在我的网站上显示“相关文章”块。为此,我使用以下查询:

SELECT *, MATCH(title, content) AGAINST('search string') AS score 
FROM news_items 
WHERE MATCH(title, content) AGAINST('search string') 
ORDER BY score DESC LIMIT 4

然而,它经常向我展示非常旧的文章,而我想展示最新的文章,所以我修改了我的查询如下:

SELECT *, MATCH(title, content) AGAINST('search string') AS score 
FROM news_items 
WHERE MATCH(title, content) AGAINST('search string') > 4 
ORDER BY ctime DESC, score DESC LIMIT 4

但在这种情况下,我无法获得最相关的文章:(

关于如何同时找到最重要和最新文章的任何想法?

提前致谢!

1 个答案:

答案 0 :(得分:3)

您可以更改为总分...这样的事情:


SELECT *, 
  (
    MATCH(title, content) AGAINST('search string')
    - 
    (ABS(DATEDIFF(`timestampfield`, NOW())) / 365)
  ) AS score 
FROM news_items 
WHERE 
  MATCH(title, content) AGAINST('search string') > 4 
ORDER BY score DESC LIMIT 4

因为有一种时髦的添加,你想要清理它:

- (ABS(DATEDIFF(`timestampfield`, NOW())) / 365)

这是分数的age分量...目前按<year> = 1 point

缩放

为此,我们首先获取时间戳字段和现在(绝对值)之间的天数:

ABS(DATEDIFF(`timestampfield`, NOW()))

然后我们缩放......

我觉得你可能根本不想根据天数放弃分数,因为如果有30天的东西它会是-30 ......看起来太苛刻了。所以我选择了几年...如果你想按周数进行扩展,除以52而不是365 ......等等。

这个比例因子将是你如何控制得分匹配和年龄之间的价值。

所以它最终会像:<match score> - <yearsAgo>


如果你这样做:

  1. 5(匹配得分) - 0.1(&lt; 1年前)= 4.9 (确定匹配,但最新)
  2. 5(匹配分数) - 0.01(&lt; 1年前)= 4.99
  3. 5(匹配分数) - 1(1年前)= 4
  4. 6(匹配得分) - 2(2年前)= 4
  5. 9(匹配得分) - 5(5年前)= 4 (最佳匹配,但旧)
  6. 7(匹配分数) - 10(10年前)= -3

  7. 注意这假设您的时间戳字段是完整的日期时间字段...否则,您需要重新转换为日期,或者直接操作unix时间戳的逻辑。

    这是查询的调试版本:

    SELECT
        `created`,
        MATCH(title, content) AGAINST('awesome') as match_score,
        (ABS(DATEDIFF(`created`, NOW())) / 365) as years_ago,
      (
        MATCH(title, content) AGAINST('awesome')
        - 
        (ABS(DATEDIFF(`created`, NOW())) / 365)
      ) AS score 
    FROM news_items 
    WHERE 
      MATCH(title, content) AGAINST('awesome') > 4 
    ORDER BY score DESC LIMIT 4