【发布时间】:2016-11-05 21:56:39
【问题描述】:
我想实现类似mysql search title, description and multi rows tag的搜索。
这是我的桌子:
书籍:
+----+-----------------------+-------------+
| id | name | description |
+----+-----------------------+-------------+
| 1 | Me Before You | [TEXT] |
| 2 | How To Win Friends... | [TEXT] |
| 3 | The Girl on the Train | [TEXT] |
| 4 | After You | [TEXT] |
| 5 | We Were Liars | [TEXT] |
+----+-----------------------+-------------+
标签:
+----+-----------------------+
| id | tag |
+----+-----------------------+
| 1 | romance |
| 2 | thriller |
| 3 | fantasy |
| 4 | science fiction |
| 5 | drama |
| 6 | friends |
+----+-----------------------+
书籍标签:
+---------+--------+
| book_id | tag_id |
+---------+--------+
| 1 | 1 |
| 1 | 3 |
| 2 | 3 |
| 3 | 3 |
| 3 | 5 |
| 4 | 1 |
| 4 | 5 |
| 4 | 6 |
| 5 | 2 |
| 5 | 6 |
+---------+--------+
以下是一些示例搜索和所需结果:
'romance' -> books 1, 4
'friends' -> books 2, 4, 5
'friends win' -> books 2
'fantasy' -> books 2, 3
'fantasy train' -> books 3
在构建 SQL 查询之前,函数会同时检查每个给定的关键字,如果它甚至是一个标签。例如,在这种情况下,我的问题是:
- 案例:3 /
- 关键词:朋友赢 /
- 标签:朋友
查询:
SELECT SQL_CALC_FOUND_ROWS
b.id, b.name,
MATCH(b.name) AGAINST('*friends* *win*' IN BOOLEAN MODE) as name_score,
MATCH(t.tag) AGAINST('friends' IN BOOLEAN MODE)as tag_score
FROM
books b
LEFT JOIN
books_tags bt ON bt.book_id = b.id
LEFT JOIN
tags t ON t.id = bt.tag_id
WHERE
MATCH(b.name) AGAINST('*friends win*' IN BOOLEAN MODE)
OR MATCH(t.tag) AGAINST('friends' IN BOOLEAN MODE)
GROUP BY
b.id
ORDER BY
name_score DESC, (tag_score + name_score) DESC
结果:
array (size=3)
0 => string '2' (length=1)
1 => string '4' (length=1)
2 => string '5' (length=1)
在这种情况下,关键字“朋友”已经与标题匹配,因此必须减少条件,不应再搜索标签。我该如何解决?
【问题讨论】:
-
你想解决/避免什么问题?
-
如果关键字已经匹配标题,标签条件
OR MATCH(t.tag) AGAINST('friends' IN BOOLEAN MODE)必须被忽略,因为重点是心情。 -
但那又怎样?为什么这有关系?性能?
-
没有。这都是关于结果的。如果关键字与标题匹配,则该关键字已过时,不得包含在搜索条件中。在我的示例中,结果是书 2、4 和 5,但必须只有书 2。
标签: php mysql search tags conditional-statements