方法:对搜索结果进行排名

时间:2020-03-05 18:48:46  来源:igfitidea点击:

我遇到了一个Webapp开发问题,为此我开发了一个解决方案,但是我试图找到其他可能解决我所遇到的性能问题的想法。

问题陈述:

  • 用户输入几个关键字/令牌
  • 应用程序搜索与令牌的匹配项
  • 根据分数对条目ID进行排序
  • 如果点值相同,则使用日期对结果进行排序

我想要做的但没有弄清楚的是,发送1个查询,该查询返回类似于in()结果的内容,但为每个标记匹配的每个令牌ID返回一个重复的条目ID。

是否有比我正在做的更好的方法,即使用多个,每个令牌运行一个查询的单个查询?如果是这样,实现这些目的最简单的方法是什么?

编辑
我已经标记了条目,例如," see spot run"的条目ID为1,三个标记" see"," spot"," run"位于单独的标记表中,具有与它们相关的条目ID,因此该表可能如下所示:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3

解决方案

回答

我们可以在MySQL中使用" UNION ALL"在一个查询中实现此目标。

只需遍历PHP中的令牌即可为每个令牌创建UNION ALL:

例如,如果标记是" x"," y"和" z",则查询可能看起来像这样

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

order子句应作为一个整体在整个结果集上运行,这就是我们所需要的。

就性能而言,它并不会那么快(我猜是这样),但是对于数据库而言,在速度方面的主要开销通常是将查询从PHP发送到数据库引擎并接收结果。使用这种技术,每个令牌只会发生一次,而不是一次,因此性能会提高,我只是不知道是否足够。

回答

如果使用的是UNION ALL模式,则可能还需要在查询中包括以下部分:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

虽然这是一个非常琐碎的示例,但它确实为我们提供了每个结果的匹配频率,并且这可能是一个伪排名。

回答

如果使用为搜索任务设计的数据结构而不是数据库,则可能会获得更好的性能。例如,我们可以尝试构建反向索引。但是,我们可能不希望自己编写它,而是希望研究像Lucene这样的东西,它可以为我们完成大部分工作。

回答

我知道这并不是我们要问的问题的严格答案,但是如果表是数千行而不是数百万行,那么FULLTEXT解决方案可能是到达此处的最佳方法。

在MySQL中,当我们在索引列上使用MATCH时,将为我们提供的每个关键字赋予一个相关性分数(大致由提及每个关键字的次数计算),该分数将比方法更准确,并且对于多个关键字肯定更为有效。

看这里:
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html