我目前为我的博客设置了一个标签系统。 每个博客都插入博客表中,标签插入到标签表中。 标记表有一列blog_id,用于将每个标记链接到博客项目。
所以让我们说:
Blog table:
id - name
20 - a nice blog post about product x
Tag table:
id - blog_id - tag
12 - 20 - nice
13 - 20 - product x
我有一个搜索功能,可以根据搜索字符串搜索标签,并且工作正常。
但我想扩展查询以搜索多个标签,并按最佳匹配排序。搜索多个标签不会有问题,因为我可以爆炸搜索字符串并循环遍历它,但是通过最佳匹配排序是我无法弄清楚的。
所以,假设我有3篇博文,每篇都有以下标签:
1.阳光,入耳式,耳机,评论
2.梨,耳罩,耳机,评论
3.梨,入耳式,耳机,评论
用户搜索“梨入耳式耳机”,我希望结果的顺序为:
3.(因为3个标签匹配)
1.(因为2个标签匹配)
2.(因为1个标签匹配)
这是查询的样子:
SELECT `b`.* FROM (`blog` b) WHERE ( b.name LIKE '%pear in-ear earphones%' OR b.id IN ( SELECT bt.blog_id FROM blog_tags bt WHERE bt.tag LIKE '%pear in-ear earphones%' AND bt.blog_id = b.id ) ) ORDER BY `b`.`date` desc
谁能救我?
我看过“全文搜索”,但这不是一个选项,因为我的表是InnoDB
提前谢谢!
答案 0 :(得分:3)
我个人喜欢使用Solr进行文字匹配。您可以创建这些复杂的公式,这些公式将使名称中的匹配比标记中的匹配更高,反之亦然。它也匹配复数。因此,如果我搜索butterflies
,它会找到butterfly
匹配。
这是另一个可以帮助您按频率订购博客标签的查询。此查询将获取标签中至少有一个匹配项的所有博客项目。它将按匹配的标签数量排序
SELECT *
FROM blog b
JOIN (
SELECT blog_id, COUNT(*) as matches
FROM tags
WHERE tag in ('pear', 'in-ear', 'earphones')
GROUP BY blog_id
) t
ON t.blog_id = b.blog_id
ORDER BY matches desc
您可以添加特定字符串的匹配数,如下所示:
SELECT *,
t.matches +
COALESCE((LENGTH(b.`title`)-LENGTH(REPLACE(b.`title`,'pear','')))/LENGTH('pear'),0) +
COALESCE((LENGTH(b.`title`)-LENGTH(REPLACE(b.`title`,'in-ear','')))/LENGTH('in-ear'),0) +
COALESCE((LENGTH(b.`title`)-LENGTH(REPLACE(b.`title`,'earphones','')))/LENGTH('earphones'),0) AS total_matches,
FROM blog b
LEFT JOIN (
SELECT blog_id, COUNT(*) as matches
FROM tags
WHERE tag in ('pear', 'in-ear', 'earphones')
GROUP BY blog_id
) t
ON t.blog_id = b.blog_id
ORDER BY total_matches desc
ORDER BY
只是注意这个查询可能会很慢,所有这些匹配和事情。我仍然建议使用像Solr
这样的索引软件答案 1 :(得分:2)
以下查询按匹配数计算与特定列表和订单匹配的标记数:
select b.*
from blog b join
blog_tags bt
on b.id = bt.blog_id
where bt.tag in ('pear', 'in-ear', 'earphones')
group by blog_id
order by COUNT(*) desc;
请注意,在原始查询中使用like
不正确。所有标签都不包含字符串'pear in-ear earphones'
。