谁能告诉我在数据库中进行这种搜索的方法?
我得到了这些表:
posts (id, tags_cache)
tags (id, name)
posts_tags (post_id, tag_id)
用户输入搜索查询(比如“water blue”),我想显示同时具有这两个标签的帖子。 我能想到的唯一搜索方法是使用 FIND_IN_SET,这样:
SELECT p.*, GROUP_CONCAT(t.name) AS tags_search
FROM posts p
LEFT JOIN posts_tags pt ON p.id = pt.post_id
LEFT JOIN tags t ON pt.tag_id = t.id
GROUP BY p.id
HAVING FIND_IN_SET('water', tags_search) > 0
AND FIND_IN_SET('blue', tags_search) > 0
posts.tags_cache
text 列存储它所属标签的名称和 id(这样:water:15 blue:20
).
为了避免通过使用此列进行搜索来进行 JOIN,我尝试了 LIKE 和 INSTR 但这些会给出不准确的结果,因为您可以搜索“ter ”,例如,您将获得标记为“water”和“termal”的帖子。我还尝试了 REGEXP,它给出了准确的结果,但这是一个缓慢的过程。
我不能使用 MATCH,因为表使用 InnoDB。
那么...是否有其他方法可以做到这一点?
[编辑]
我忘了说用户可以搜索很多标签(不仅仅是 2 个),甚至可以排除标签:搜索标签为“water”但不是“blue”的帖子。使用 FIND_IN_SET 这对我有用:
HAVING FIND_IN_SET('water', tags_search) > 0
AND NOT FIND_IN_SET('blue', tags_search) > 0
[编辑2]
我按照 ypercube 的建议做了一些性能测试(即只检查查询花费了多长时间,缓存),结果如下:
muists | Bill K | ypercu | includes:excludes
--------------------------
0.0137 | 0.0009 | 0.0029 | 2:0
0.0096 | 0.0081 | 0.0033 | 2:1
0.0111 | 0.0174 | 0.0033 | 2:2
0.0281 | 0.0081 | 0.0025 | 5:1
0.0014 | 0.0013 | 0.0015 | 0:2
我不知道这个信息是否是有效资源...但它表明 ypercube 的每个标签 JOIN 方法是最快的。
最佳答案
我不明白您为什么不想使用 JOIN,也不明白您为什么要尝试使用 LEFT JOIN。您正在寻找存在的东西(而不是可能存在的东西),所以去掉 LEFT JOIN 并只加入 JOIN。并删除 tags_cache
列,你只是在自找麻烦。
你要找的就是这样的东西:
select p.id
from posts p
join posts_tags pt on p.id = pt.post_id
join tags t on pt.tag_id = t.id
where t.name in ('water', 'blue')
group by p.id
having count(t.id) = 2
HAVING 子句中的 2
是您要查找的标签数。
如果你想排除某些标签,你可以像这样将它添加到 WHERE 子句中:
select p.id
from posts p
join posts_tags pt on p.id = pt.post_id
join tags t on pt.tag_id = t.id
where t.name in ('water', 'blue')
and p.id not in (
select pt.post_id
from posts_tags pt
join tags t on pt.tag_id = t.id
where t.name in ('pancakes', 'eggs') -- Exclude these
)
group by p.id
having count(t.id) = 2
关于mysql - 如何使用 JOIN 在 MySQL 上进行搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8106547/