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

MySQL fulltext search and sort by relevance + TIME

我正在尝试在我的网站上显示 "related articles" 块。为此,我使用以下查询:

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

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

关于如何同时找到最相关和最新的文章有什么想法吗?

提前致谢!

您可以更改为总分...像这样:


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(<1 年前)= 4.9 (匹配,但最新)
  2. 5(匹配分数)- 0.01(<1 年前)= 4.99
  3. 5(比赛得分)- 1(1 年前)= 4
  4. 6(比赛得分)- 2(2 年前)= 4
  5. 9(匹配分数)- 5(5 年前)= 4 (最佳匹配,但旧)
  6. 7(比赛得分)- 10(10 年前)= -3

注意这假定您的时间戳字段是一个完整的日期时间字段...否则,您将需要重新转换为日期,或者直接操作 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