假设我有两列,关键字和内容.我有两个全文索引.我希望关键字中的foo行与内容中的foo行具有更多相关性.我需要做些什么才能使MySQL对关键字中的匹配项进行加权?
我正在使用"匹配"语法.
解:
能够以下列方式完成这项工作:
SELECT *, CASE when Keywords like '%watermelon%' then 1 else 0 END as keywordmatch, CASE when Content like '%watermelon%' then 1 else 0 END as contentmatch, MATCH (Title, Keywords, Content) AGAINST ('watermelon') AS relevance FROM about_data WHERE MATCH(Title, Keywords, Content) AGAINST ('watermelon' IN BOOLEAN MODE) HAVING relevance > 0 ORDER by keywordmatch desc, contentmatch desc, relevance desc
mintywalker.. 81
创建三个全文索引
a)关键字列中的一个
b)内容栏中的一个
c)关键字和内容列中的一个
然后,您的查询:
SELECT id, keyword, content, MATCH (keyword) AGAINST ('watermelon') AS rel1, MATCH (content) AGAINST ('watermelon') AS rel2 FROM table WHERE MATCH (keyword,content) AGAINST ('watermelon') ORDER BY (rel1*1.5)+(rel2) DESC
关键在于,rel1
只在keyword
列中为您提供查询的相关性(因为您仅在该列上创建了索引). rel2
做同样的事情,但对于content
专栏.您现在可以将这两个相关性分数一起应用于您喜欢的任何权重.
但是,您没有将这两个索引中的任何一个用于实际搜索.为此,您使用第三个索引,它位于两列上.
(关键字,内容)上的索引控制您的召回.阿卡,还有什么.
两个单独的索引(一个仅关键字,一个仅关于内容)控制您的相关性.您可以在此处应用自己的加权标准.
请注意,您可以使用任意数量的不同索引(或者根据其他因素改变您在查询时使用的索引和权重...如果查询包含停用词,则仅搜索关键字...减少加权偏差关键字,如果查询包含超过3个单词...等).
每个索引都占用磁盘空间,因此索引越多,磁盘越多.而反过来,mysql的内存占用更高.此外,插入将花费更长时间,因为您有更多的索引要更新.
对于您的情况,您应该对性能进行基准测试(小心关闭mysql查询缓存以进行基准测试,否则您的结果将会出现偏差).这不是谷歌级效率,但它非常容易和"开箱即用",它几乎肯定比你在查询中使用"喜欢"好很多.
我发现它的效果非常好.
创建三个全文索引
a)关键字列中的一个
b)内容栏中的一个
c)关键字和内容列中的一个
然后,您的查询:
SELECT id, keyword, content, MATCH (keyword) AGAINST ('watermelon') AS rel1, MATCH (content) AGAINST ('watermelon') AS rel2 FROM table WHERE MATCH (keyword,content) AGAINST ('watermelon') ORDER BY (rel1*1.5)+(rel2) DESC
关键在于,rel1
只在keyword
列中为您提供查询的相关性(因为您仅在该列上创建了索引). rel2
做同样的事情,但对于content
专栏.您现在可以将这两个相关性分数一起应用于您喜欢的任何权重.
但是,您没有将这两个索引中的任何一个用于实际搜索.为此,您使用第三个索引,它位于两列上.
(关键字,内容)上的索引控制您的召回.阿卡,还有什么.
两个单独的索引(一个仅关键字,一个仅关于内容)控制您的相关性.您可以在此处应用自己的加权标准.
请注意,您可以使用任意数量的不同索引(或者根据其他因素改变您在查询时使用的索引和权重...如果查询包含停用词,则仅搜索关键字...减少加权偏差关键字,如果查询包含超过3个单词...等).
每个索引都占用磁盘空间,因此索引越多,磁盘越多.而反过来,mysql的内存占用更高.此外,插入将花费更长时间,因为您有更多的索引要更新.
对于您的情况,您应该对性能进行基准测试(小心关闭mysql查询缓存以进行基准测试,否则您的结果将会出现偏差).这不是谷歌级效率,但它非常容易和"开箱即用",它几乎肯定比你在查询中使用"喜欢"好很多.
我发现它的效果非常好.
实际上,使用case语句来生成一对标志可能是更好的解决方案:
select ... , case when keyword like '%' + @input + '%' then 1 else 0 end as keywordmatch , case when content like '%' + @input + '%' then 1 else 0 end as contentmatch -- or whatever check you use for the matching from ... and here the rest of your usual matching query ... order by keywordmatch desc, contentmatch desc
同样,只有当所有关键字匹配排名高于所有仅内容匹配时,才会这样.我还假设关键字和内容的匹配是最高等级.
仅使用2个全文索引的简化版本(贷记来自@mintywalker):
SELECT id, MATCH (`content_ft`) AGAINST ('keyword*' IN BOOLEAN MODE) AS relevance1, MATCH (`title_ft`) AGAINST ('keyword*' IN BOOLEAN MODE) AS relevance2 FROM search_table HAVING (relevance1 + relevance2) > 0 ORDER BY (relevance1 * 1.5) + (relevance2) DESC LIMIT 0, 1000;
这将针对检索两个完全索引的列,keyword
然后将匹配的相关性选择为两个单独的列。我们将排除不匹配项(关联1和关联2均为零),并通过增加content_ft
列的权重对结果进行重新排序。我们不需要复合全文索引。