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 WHERETABLE_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() - 按相关性和列排序?