MySQL match() against() - 按相关性和列排序?

Posted

技术标签:

【中文标题】MySQL match() against() - 按相关性和列排序?【英文标题】:MySQL match() against() - order by relevance and column? 【发布时间】:2011-09-09 17:16:48 【问题描述】:

好的,所以我正在尝试在多个列中进行全文搜索,就像这样简单:

SELECT * FROM pages WHERE MATCH(head, body) AGAINST('some words' IN BOOLEAN MODE)

现在我想按相关性排序,(找到多少个单词?)我已经能够用这样的东西来做:

SELECT * , MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE) AS relevance 
FROM pages
WHERE MATCH (head, body) AGAINST ('some words' IN BOOLEAN MODE)
ORDER BY relevance

现在是我迷路的部分,我想优先考虑head 列中的相关性。

我想我可以创建两个相关性列,一个用于head,一个用于body,但那时我会在表格中进行三次相同的搜索,以及我正在制作的内容这个函数,性能很重要,因为查询将被连接并与其他表匹配。

那么,我的主要问题是,是否有更快的方法来搜索相关性并确定某些列的优先级? (作为奖励,甚至可能使相关性计数单词在列中出现的次数?)

任何建议或意见都会很棒。

注意:我将在 LAMP 服务器上运行它。 (本地测试中的 WAMP)

【问题讨论】:

您真的必须在 WHERE 子句中的 SELECT 子句 中都添加 MATCH...AGAINST 吗?不能在 SELECT 子句中给它取别名,在 WHERE 子句中引用别名吗?我正在尝试使用准备好的语句,这对我来说似乎是多余的/奇怪的。 不,正如 mysql 文档自 5.5 以来所述,MATCH ... AGAINST 将在 SELECT 和 WHERE 中计算一次,因此没有额外的开销。 【参考方案1】:

补充一点,如果您使用自定义排名,请记住使用 HAVING 而不是 WHERE 来减少负载。

SELECT MATCH(x,y) AGAINST (? IN BOOLEAN MODE) AS r1,
MATCH(z) AGAINST (? IN BOOLEAN MODE) AS r2,
...
FROM table 
HAVING (r1 + r2) > 0
ORDER BY (r1 * 3 + r2) DESC
LIMIT 10

【讨论】:

【参考方案2】:

只是为可能需要的人添加.. 不要忘记更改表格!

ALTER TABLE table_name ADD FULLTEXT(column_name);

【讨论】:

如果您多次执行上述命令,则会为同一列创建多个索引。因此,只需运行此命令一次。 更好的是,在 tablename(column_name(s)) 上使用 CREATE FULLTEXT INDEX indexname。在尝试创建索引之前,您还应该真正检查索引是否存在。您可以使用以下方法检查它是否存在:SELECT INDEX_NAME FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_CATALOG = 'def' AND TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tablename' AND INDEX_NAME = 'indexname';【参考方案3】:

我也只是在玩这个。添加额外权重的一种方法是在代码的 ORDER BY 区域中。

例如,如果您要匹配 3 个不同的列,并希望增加某些列的权重:

SELECT search.*,
MATCH (name) AGAINST ('black' IN BOOLEAN MODE) AS name_match,
MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE) AS keyword_match,
MATCH (description) AGAINST ('black' IN BOOLEAN MODE) AS description_match
FROM search
WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE)
ORDER BY (name_match * 3  + keyword_match * 2  + description_match) DESC LIMIT 0,100;

【讨论】:

这不是一个很繁重的查询吗? 将数学运算移到 select 语句中,大大减轻了负载。 SELECT search.*, (MATCH (name) AGAINST ('black' IN BOOLEAN MODE) * 3) + (MATCH (keywords) AGAINST ('black' IN BOOLEAN MODE)*2 + MATCH (description) AGAINST ('black' IN BOOLEAN MODE)) AS totalScore , FROM search WHERE MATCH (name, keywords, description) AGAINST ('black' IN BOOLEAN MODE) ORDER BY totalScore DESC LIMIT 0,100;【参考方案4】:

可能会增加与您想要的头部的相关性。它不会翻倍,但对你来说可能就足够了:

SELECT pages.*,
       MATCH (head, body) AGAINST ('some words') AS relevance,
       MATCH (head) AGAINST ('some words') AS title_relevance
FROM pages
WHERE MATCH (head, body) AGAINST ('some words')
ORDER BY title_relevance DESC, relevance DESC

-- alternatively:
ORDER BY title_relevance + relevance DESC

如果您可以灵活地切换数据库引擎,您还想研究的另一种方法是Postgres。它允许设置运营商的权重并调整排名。

【讨论】:

顺便说一句,MySQL 5.6 支持对 InnoDB 表的全文搜索! 你能为此提供一个 SQL fiddle 吗? 多次搜索有多大的负面影响?我需要 4 次匹配我的 SELECT,因为我有 4 个不同的权重因子。这会降低性能吗? @ToBe 我在其他类似问题上看到不止一个人说,由于 MySQL 内部的工作方式,使用多个 MATCH 语句没有额外开销。 确保运行这两个。 ALTER TABLE talk_webpages ADD FULLTEXT(head)ALTER TABLE talk_webpages ADD FULLTEXT(head, body)【参考方案5】:

我从来没有这样做过,但是好像

MATCH (head, head, body) AGAINST ('some words' IN BOOLEAN MODE)

应该给头部中的匹配项加倍权重。


刚刚阅读docs page上的这条评论,认为它可能对你有价值:

Patrick O'Lone 于 12 月 9 日发布 2002 年上午 6 点 51 分

需要注意的是 布尔模式下的文档 几乎总是会返回相关性 1.0。为了获得相关性 这很有意义,您需要:

SELECT MATCH('Content') AGAINST ('keyword1 keyword2') as Relevance 
FROM table 
WHERE MATCH ('Content') AGAINST('+keyword1+keyword2' IN BOOLEAN MODE) 
HAVING Relevance > 0.2 
ORDER BY Relevance DESC 

注意你是 做一个定期的相关性查询 获得相关因素结合 使用 BOOLEAN MODE 的 WHERE 子句。 BOOLEAN MODE 为您提供子集 满足要求的 BOOLEAN 搜索,相关性查询 满足相关因子,并且 HAVING 子句(在这种情况下)确保 该文件与 搜索(即得分较低的文档 小于 0.2 被认为是不相关的)。 这也允许您订购 关联。 这可能或可能 不是 IN 的方式中的错误 布尔模式运行,虽然 我在邮件列表中读到的 cmets 建议在布尔模式下 相关性排名不是很 复杂,因此借给自己 实际提供相关性较差 文件。顺便说一句 - 我没有注意到 这样做的性能损失,因为 看来MySQL只执行 FULLTEXT 搜索一次,即使 两个 MATCH 子句是不同的。采用 解释来证明这一点。

所以看起来你可能不需要担心调用全文搜索两次,尽管你仍然应该“使用 EXPLAIN 来证明这一点”

【讨论】:

向 match() 函数添加两次 head 不起作用,遗憾的是。也许是因为查询不计算单词出现的次数?而且我也一直在使用您所指的那个页面,但由于某种原因我不能让它工作......我还没有索引我的列,因此如果没有“IN BOOLEAN MODE”标签就无法搜索...... . 我认为非布尔搜索会返回出现次数,但布尔搜索不会? 我会在明天进行更多研究,但我会暂时持有。感谢您的回答,当我掌握这个时,我们会看看它是否对我有帮助。 我在使用 IN BOOLEAN MODE 然后按相关性排序时遇到问题,这解决了我的问题,相关性总是返回为 1。谢谢。 生成分数字段解决了我的问题:我得到了结果,但其中很多都是完全的噪音。谢谢,+1

以上是关于MySQL match() against() - 按相关性和列排序?的主要内容,如果未能解决你的问题,请参考以下文章

mysql全文索引用于 MATCH() AGAINST 但不用于 =

Mysql利用match...against进行全文检索

MySQL match() against() - 按相关性和列排序?

mysql 全文模糊搜索MATCH AGAINST方法

MySQL MATCH() AGAINST() FULLTEXT Index - 结合短语匹配实现部分字符串匹配

MySql `MATCH AGAINST` 和 `LIKE` 组合搜索特殊字符