我正在建立一个网站,该网站将有一个可搜索的产品数据库。为了简单起见,我的表有三列:
- id
- img(对产品图像的引用)
- 标签(varchar 255,用于搜索的标签列表,例如"椅子木棕色")
我有一个问题:
$query = "SELECT `img` FROM `products` WHERE `tags` LIKE '%$q%'";
这正是我想要的方式,唯一的问题是,如果标签按搜索顺序排列,它只会选择行。例如,如果有3行:
- 标签为"黑色托盘"的第1行
- 第2行,标签为"托盘黑色"
- 第3行,标签为"黑色托盘层"
当您搜索"黑色托盘"时,第1行和第3行都会显示,但第2行不会显示。
无论单词的顺序如何,我都试图显示所有三行。例如,我希望,如果你搜索"黑色托盘",它们都会显示,但如果你搜索了"托盘层",那么只有第3行会显示。也许这需要重新思考最初的查询,我不确定。
非常感谢!
您需要使用功能强大得多的MATCH AGAINST
。此外,你还可以对所有内容进行索引,并提高速度。
请参阅以下页面:
- http://dev.mysql.com/doc/refman/5.5/en/fulltext-search.html
- http://dev.mysql.com/doc/refman/5.7/en/fulltext-natural-language.html
这可能太晚了,但如果可能的话,请为您的标签使用另一个表格,格式为:
product_id | tag
1 | black
1 | tray
2 | tray
2 | black
3 | black
3 | tray
3 | layer
这将允许您使用以下内容查找作为一个或多个标签的任何产品:
SELECT DISTINCT products.*
FROM products LEFT JOIN tags ON tags.product_id = products.id
WHERE tags.tag IN ('black', 'red', 'light')
编辑
如果你想让所有标签都存在,你必须向x个标签发出x个查询才能使用这个进行搜索:
SELECT *
FROM
(SELECT DISTINCT products.*
FROM products LEFT JOIN tags ON tags.product_id = products.id
WHERE tags.tag = 'black') AS set_a
INNER JOIN
(SELECT DISTINCT products.*
FROM products LEFT JOIN tags ON tags.product_id = products.id
WHERE tags.tag ='red') AS set_b ON set_a.product_id = set_b.product_id
INNER JOIN
(SELECT DISTINCT products.*
FROM products LEFT JOIN tags ON tags.product_id = products.id
WHERE tags.tag = 'light') AS set_c ON set_b.product_id = set_c.product_id
这将与找到的所有记录相交,只留下潜在的记录。请注意,这是一个非常繁重的请求,我不知道INTERSECT关键字是否已经在MySQL中实现,我相信这将是一个更好的方法!
我建议将单个单词标记存储在一个单独的关系(表)中,并且:
preg_replace(''s+', "','", $q);
$query = "SELECT `img` FROM `products` LEFT JOIN `tags` USING (`id`) WHERE `tags`.`content` IN ('$q')";