php - mysql搜索标题、描述和多行标签(关于条件)

标签 php mysql search tags conditional-statements

我想实现类似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 查询之前,一个函数会检查每个给定的关键字,如果它是一次标记。例如,在这种情况下,我的问题是:

  • 案例:3/
  • 关键词: friend 赢/
  • 标签: friend

查询:

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)

在这种情况下,关键字“friends”已经与标题匹配,因此必须减少条件并且不应再搜索标签。我该如何解决?

最佳答案

这就是你想要的吗?...

数据集

DROP TABLE IF EXISTS books;

CREATE TABLE books
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(50) NOT NULL
,FULLTEXT(name)
) ENGINE = MyISAM;

INSERT INTO books VALUES
(1,'Me Before You'),
(2,'How To Win Friends...'),
(3,'The Girl on the Train'),
(4,'After You'),
(5,'We Were Liars');

DROP TABLE IF EXISTS tags;

CREATE TABLE tags
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,tag VARCHAR(20) NOT NULL
);

INSERT INTO tags VALUES
(1,'romance'),
(2,'thriller'),
(3,'fantasy'),
(4,'science fiction'),
(5,'drama'),
(6,'friends');

DROP TABLE IF EXISTS books_tags;

CREATE TABLE books_tags
(book_id INT NOT NULL
,tag_id INT NOT NULL
,PRIMARY KEY(book_id,tag_id)
);

INSERT INTO books_tags VALUES
(1,1),
(1,3),
(2,3),
(3,3),
(3,5),
(4,1),
(4,5),
(4,6),
(5,2),
(5,6);

查询和结果

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 |
+----+-----------------------+------------+

关于php - mysql搜索标题、描述和多行标签(关于条件),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38180116/

相关文章:

php - 比较数组与数据库,取消设置值,而不丢失偏移量?

mysql - 有没有办法强制至少一列不为空

Android:在 SearchView 中输入文本时防止弹出文本字段

php - Laravel 用户::创建缺失数据

javascript - 将 php 变量访问到外部 javascript 文件中

php - 正则表达式选择某个单词后跟整数或小数?

php - 将文本文件每行上传到 mysql 行

mysql - 将列从 CSV 导入现有的 MySQL 表

使用多个关键字的 Jquery Grep 和 Map Json

php - 未找到结果