如何:排名搜索结果

10

我有一个 WebApp 开发问题,我已经开发了一种解决方案,但尝试寻找其他的想法,以解决我看到的一些性能问题。

问题陈述:

  • 用户输入多个关键词/标记
  • 应用程序搜索与标记匹配的结果
  • 每个标记需要一个结果
    • 例如,如果条目有 3 个标记,则需要 3 次条目 ID
  • 排列结果
    • 为标记匹配分配 X 分数
    • 根据分数对条目 ID 进行排序
    • 如果分数相同,则使用日期对结果进行排序

我想要做到的,但还没有想出方法的是,发送一个查询返回类似于 in() 结果的东西,但对于每个条目 ID 检查的每个标记匹配都返回重复的条目 ID。

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

编辑
我已经对条目进行了标记化,因此,例如,“see spot run” 具有 ID 为 1 的条目 ID,三个标记,“see”,“spot”,“run”,它们在一个单独的标记表中,与它们相关的条目 ID 所以表可能看起来像这样:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
4个回答

6

您可以在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...

订单子句应该作用于整个结果集,这正是您所需要的。

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


@rmbarnes - 这一定是我几年前在数据库基础知识中看到的那些 UNION 操作突然变得有意义的地方;我一定会进行性能测试,看看它在总体速度上与其他方法相比如何。 - warren
请记得使用 UNION ALL 而不是仅使用 UNION,否则我认为您将无法获得您想要的具有相同 ID 的多行返回。- rmbarnes Sep 6 '08 at 20:23 - warren

3
我知道这并不是你所问问题的严格答案,但如果你的表只有几千行而不是几百万行,那么全文搜索可能是最好的解决方案。在MySQL中,当你在索引列上使用MATCH时,你提供的每个关键字都会被赋予一个相关度分数(大致由每个关键字被提及的次数计算),这将比你的方法更准确,对于多个关键字来说也更有效率。参见这里:http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

1
如果您正在使用 UNION ALL 模式,您可能还想将以下部分包含到查询中:
SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

虽然这只是一个非常简单的示例,但它确实可以让您获得每个结果匹配频率,并且这可能是一个起点伪排名。

-1

如果您使用专门用于搜索任务的数据结构而不是数据库,您可能会获得更好的性能。例如,您可以尝试构建一个倒排索引。但是,您可能还想查看类似Lucene这样的工具,它可以为您完成大部分工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接