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


80

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

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在本地测试中)


您真的必须在SELECT子句WHERE子句中都放入MATCH ... AGAINST吗?您不能在SELECT子句中为它加上别名,而在WHERE子句中引用它吗?我正在尝试使用准备好的语句,这对我来说似乎是多余的/奇怪的。
S. Imp

2
否,正如从5.5版本起的MySQL文档所述,在SELECT和WHERE中,MATCH ... AGAINST都将被计算一次,因此不会产生额外的开销。
Bob2u

Answers:


156

可能会增加与所需头部的相关性。它不会使它加倍,但是对于您而言,它可能已经足够好了:

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。它允许设置运营商的权重并进行排名。


14
顺便说一句,MySQL 5.6支持在InnoDB表上进行全文搜索!
Jabari

1
您可以为此提供SQL提琴吗?
用户

多次搜索有多少负面影响?我需要4个匹配项,因为我有4个不同的权重因子。这会降低性能吗?
ToBe 2015年

@ToBe在其他类似问题上,我不止一个人说过MATCH,由于MySQL内部工作的方式,使用多条语句不会产生额外的开销。
BadHorsie

确保运行这两个。ALTER TABLE talk_webpages ADD FULLTEXT(head)ALTER TABLE talk_webpages ADD FULLTEXT(head, body)
Supun Kavinda '19

14

只需添加可能需要的人即可。不要忘记更改表格!

ALTER TABLE table_name ADD FULLTEXT(column_name);

3
如果您多次执行以上命令,则将为同一列创建多个索引。因此,只运行一次此命令。
hakiko

更好的是,在表名(column_name(s))上使用CREATE FULLTEXT INDEX索引名。在尝试创建索引之前,您还应该真正检查索引是否存在。您可以使用以下命令检查其是否存在:从INFORMATION_SCHEMA.STATISTICS WHERE TABLE_CATALOG='def'AND TABLE_SCHEMA= DATABASE()AND TABLE_NAME='tablename'AND INDEX_NAME='indexname';
Dave Hilditch

9

我从未这样做过,但似乎

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

应该给头部找到的火柴加倍的重量。


只需在docs页面上阅读此评论,以为它可能对您有价值:

帕特里克·奥隆(Patrick O'Lone)发表于2002年12月9日上午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 BOOLEAN MODE的相关性等级并不十分复杂,所以这可能不是IN BOOLEAN MODE运作方式中的错误,因此,对于实际提供相关文档而言,这本身就很差。顺便说一句-我没有注意到这样做的性能损失,因为即使两个MATCH子句不同,MySQL似乎只执行一次FULLTEXT搜索。使用EXPLAIN来证明这一点。

因此,尽管您仍然应该“使用EXPLAIN证明这一点”,但您似乎不必担心调用两次全文搜索。


1
不幸的是,将头两次添加到match()函数不起作用。也许是因为查询没有计算单词出现的次数?而且我也一直在使用您引用的页面,但是由于某种原因我无法使其正常工作...我尚未为列编制索引,因此如果没有“ IN BOOLEAN MODE”标签,就无法搜索。 。
的Kristoffer拉艺典三重奏

我认为非booleen搜索将返回出现次数,但booleen不会吗?
jisaacstone 2011年

明天我会对其进行更多研究,但是我现在要坚持。感谢您的回答,当我掌握这一点时,我们会看看它是否对我有帮助。
Kristoffer la Cour

我在使用IN BOOLEAN MODE时遇到问题,然后按相关性排序,这解决了我的相关性问题,始终将相关性返回为1。谢谢。
Jazzy 2012年

生成得分字段解决了我的问题:我正在获得结果,但是其中很多都是完全的噪音。谢谢,+ 1
克里斯·贝克

4

我也只是在玩这个。添加额外权重的一种方法是在代码的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;

这不是一个很繁重的查询吗?
Beanow 2013年

5
将数学移动到选择语句中,可以大大减轻工作量。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;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.