当前位置:  开发笔记 > 后端 > 正文

如何操纵MySQL全文搜索相关性以使一个字段比另一个字段更"有价值"?

如何解决《如何操纵MySQL全文搜索相关性以使一个字段比另一个字段更"有价值"?》经验,为你挑选了3个好方法。

假设我有两列,关键字和内容.我有两个全文索引.我希望关键字中的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查询缓存以进行基准测试,否则您的结果将会出现偏差).这不是谷歌级效率,但它非常容易和"开箱即用",它几乎肯定比你在查询中使用"喜欢"好很多.

我发现它的效果非常好.



1> mintywalker..:

创建三个全文索引

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查询缓存以进行基准测试,否则您的结果将会出现偏差).这不是谷歌级效率,但它非常容易和"开箱即用",它几乎肯定比你在查询中使用"喜欢"好很多.

我发现它的效果非常好.


@mintywalker命令By不应该是`ORDER BY(rel1*1.5)+(rel2)DESC`以获得最高分,因此首先更相关?
@PanPipes是的它应该是`DESC`,因为更高的相关性是更好的匹配

2> notnot..:

实际上,使用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

同样,只有当所有关键字匹配排名高于所有仅内容匹配时,才会这样.我还假设关键字和内容的匹配是最高等级.


使用like语句不是运行搜索的好方法.首先,除非你拆分字符串,否则你只会按照确切的顺序进行匹配.即搜索"LIKE"%T恤red%''与数据库中的"红色T恤"不匹配.其次,您最终会有更长的时间来执行查询,因为LIKE会执行全表扫描.
@ChrisG`LIKE`在`FROM`子句中使用而不是在`SELECT`中进行全表扫描

3> lubosdz..:

仅使用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列的权重对结果进行重新排序。我们不需要复合全文索引。

推荐阅读
李桂平2402851397
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有