我想实现类似于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 |
+----+-----------------------+
Books_tags :
+---------+--------+
| 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查询之前,函数会检查每个给定的关键字,如果它甚至是一次标记。我的问题是,例如,在这种情况下:
查询:
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)
在这种情况下,关键字'朋友'已经匹配标题,因此必须减少条件,不再搜索标签。我该如何解决?
答案 0 :(得分:0)
这就是你之后的事情吗?...
数据集
SELECT DISTINCT b.*
, MATCH(b.name) AGAINST('*friends* *win*' IN BOOLEAN MODE) name_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
AND t.tag IN ('friends','win')
WHERE t.id IS NULL;
+----+-----------------------+------------+
| id | name | name_score |
+----+-----------------------+------------+
| 1 | Me Before You | 0 |
| 2 | How To Win Friends... | 1 |
| 3 | The Girl on the Train | 0 |
| 4 | After You | 0 |
| 5 | We Were Liars | 0 |
+----+-----------------------+------------+
查询和结果
Get-Content
答案 1 :(得分:0)
好的,最后我写了一个函数,为我生成一个有效的查询。该功能非常复杂,取决于多个用户输入。 解决方案是连接t.tag和b.name 。这就是我的WHERE条件看起来如何,它对我来说很好用:
... WHERE ap.active='yes'
AND (LOWER(CONCAT_WS(' ', IF(LENGTH(t.tag), t.tag, NULL), IF(LENGTH(b.name), b.name, NULL) )) REGEXP 'friends'
AND LOWER(CONCAT_WS(' ', IF(LENGTH(t.tag), t.tag, NULL), IF(LENGTH(b.name), b.name, NULL) )) REGEXP 'win')
GROUP BY b.id