目前在作“Brick4.com - 国产积木索引表”这个小工具。它是看成“工具书”而存在的,必然须要一个靠谱的检索功能。按主题和品牌这些即有的筛选就不说了,今天把个人摸索过程整理一下,说说如何用 MySQL 实现多关键词站内“模糊查找”。sql
拿一个简化的小表儿作例子工具
表名叫:article
字段有:title、subtitle、tag、text……优化
涉及到查找的字段有三个:title、subtitle、tagcode
像我这种初学者,首先想到的确定是 LIKE ,关键词是“车”的话,就这样:orm
SELECT * FROM article WHERE title LIKE "%车%" OR subtitle LIKE "%车%" OR tag LIKE "%车%"
怎么样?LIKE 是万能的,用一个 LIKE 解决不了的事情就多用几个 LIKE 。因而多关键词就这样搞:blog
SELECT * FROM article WHERE ( title LIKE "%车%" OR subtitle LIKE "%车%" OR tag LIKE "%车%" ) OR ( title LIKE "%摩托%" OR subtitle LIKE "%摩托%" OR tag LIKE "%摩托%" ) OR ( title LIKE "%红色%" OR subtitle LIKE "%红色%" OR tag LIKE "%红色%" ) OR ( title LIKE "%美国%" OR subtitle LIKE "%美国%" OR tag LIKE "%美国%" ) OR ( title LIKE "%2006%" OR subtitle LIKE "%2006%" OR tag LIKE "%2006%" )
虽然很工整,不过能不能简洁一点?固然行!看我变形!咱们能够用正则:排序
SELECT * FROM article WHERE title REGEXP "车|摩托|红色|美国|2006" OR subtitle REGEXP "车|摩托|红色|美国|2006" OR tag REGEXP "车|摩托|红色|美国|2006"
怎么样?意外不意外?惊喜不惊喜?其实我们还能够更进一步,把几个字段合并起来:索引
SELECT * FROM article WHERE CONCAT_WS(" ", title, subtitle, tag) REGEXP "车|摩托|红色|美国|2006"
这一句话,和前面洋洋洒洒那一大坨是等同的。字符串
之因此用 CONCAT_WS()
而不是 CONCAT()
,是由于后者在某字段为 NULL 的状况下会致使合并结果为 NULL,万无一失嘛,咱们用前者。get
要求不高的话,到这其实就能够了。可是总感受找到的文章似有关联又东一榔头西一杵,因此我们要排序。我但愿“按照匹配关键词的多寡来排序”,匹配关键词越多的文章越靠前,咋办呢?
SELECT *, ( (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%车%", 1, 0)) + (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%摩托%", 1, 0)) + (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%红色%", 1, 0)) + (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%美国%", 1, 0)) + (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%2006%", 1, 0)) ) AS keyweight FROM article WHERE CONCAT_WS(" ", title, subtitle, tag) REGEXP "车|摩托|红色|美国|2006" ORDER BY keyweight DESC
“经过一组关键词站内模糊搜索,按照匹配关键词的多寡来排序。”这个需求,目标达成!撒花撒花~
最终的语句扔在这里,相信你一看就懂了。关键是思路,我但是沥沥拉拉摸索了好几天啊……
在今天的例子里 title、subtitle、tag 三个字段同等重要,因此直接合并起来,若是你但愿有权重的概念,好比 主标题 大于 副标题 大于 标签,思考一下,其实也不复杂。
最后再打个广告:Brick4.com - 最实用的国产积木索引表 更好用了!感兴趣的小伙伴快来支持一下!!
2017-09-13 更新
发现 Brick4 搜索的关键词开始区分大小写了。探究源头是由于最近把一个数据类型为 INT 的字段归入了检索,区分大小写正是所以形成的。
举个例子,好比 time 的数据类型是数字,title 是文本,直接这样写就会区分大小写:
SELECT * FROM article WHERE CONCAT_WS("", time, title) REGEXP "关键词"
要是把数字转成字符串再拼合就没事了:
============================================================================SELECT * FROM article WHERE CONCAT_WS("", CHAR(time), title) REGEXP "关键词"
上述转自:
http://lao.si/120
今天一同事碰到一奇葩需求。
多个模糊查询结果 优先按照某一个模糊查询匹配
思路一:优先的模糊查询先查 union 其余的模糊查询结果 再分页,可是花费时间*2
思路二:产品角度考虑,既然优先某一个模糊查询,能够分为两个查询页面/采用tab页形式,,
ok sql级别的模糊查询就这样了。。多个角度优化