За последние 24 часа нас посетили 21607 программистов и 1018 роботов. Сейчас ищут 698 программистов ...

Реализация поиска по тегам(категории).

Тема в разделе "MySQL", создана пользователем cadijob, 17 июл 2017.

  1. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Привет.
    Хочу реализовать поиск на сайте с помощью тегов(в будущем будет ajax, но я думаю, сейчас это не важно).
    У одной статьи может быть от одного до пятнадцати тегов.
    Вот как я думаю:
    Таблица tags:
    alias - имя для ссылки в html(href).
    name - имя для html
    id - id категории...

    Таблица articles:
    id - id статьи
    title - title
    fullText- ну тут понятно
    .
    Так вот.. Может создать в таблице articles поле типа text. И при создании статьи загружать через запятую категорию. Нормально? Удобно ли потом будет делать поиск по тегам(ajax) или есть вариант получше?
     
  2. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    для тегов нужно три таблицы.. почитайте про связь многое к многим..
     
    cadijob нравится это.
  3. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Ага. Прочитал. Спасибо. Просто интересно, это нормально? Или типа самый легкий путь?
    --- Добавлено ---
    В новой таблице articlesTags где будет id article и id tags больше, как я понял, ни каких полей не нужно?
     
  4. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    правильно..
    одна таблица с сообщениями
    одна таблица с тегами
    одна таблица связывающая

    в таблице с тегами два поля по сути, автоинкрементный tag_id и уникальный tag_name
    в связывающей таблице тоже два поля.. post_id и tag_id теоретически можно их связать внешними ключами с родительскими таблицами..
     
  5. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Создал как и сказали, добавил индексы к новым таблицам. Работаю в phpmyadmin. Но как только пытаюсь что-то связать - ошибка #1215. Куда нужно добавить первичный ключ?
     
  6. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    в промежуточную таблицу, которая связывает таблицу постов и тегов..
     
  7. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Но ведь он может быть только один. А в промежуточной таблице два поля.
     
  8. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    в промежуточной таблице два поля
    post_id
    tag_id

    назначаете post_id внешний ключ из таблицы post столбец id
    тоже самое делаете для тега только естественно для таблица tags
    в phpMyAdmin есть кнопка СТРУКТУРА/СВЯЗИ - там наглядно все показано..
     
  9. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Если нужно это делать через ограничение внешнего ключа, то ошибка #1215
     
  10. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    вот пример
    PHP:
    1. -- phpMyAdmin SQL Dump
    2. -- version 4.6.5.2
    3. -- https://www.phpmyadmin.net/
    4. --
    5. -- Хост: 127.0.0.1:3306
    6. -- Время создания: Июл 18 2017 г., 00:37
    7. -- Версия сервера: 5.6.34
    8. -- Версия PHP: 7.1.0
    9.  
    10. SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
    11. SET time_zone = "+00:00";
    12.  
    13. --
    14. -- База данных: `test1`
    15. --
    16.  
    17. -- --------------------------------------------------------
    18.  
    19. --
    20. -- Структура таблицы `link_post_tag`
    21. --
    22.  
    23. CREATE TABLE `link_post_tag` (
    24.   `post_id` int(10) NOT NULL,
    25.   `tag_id` int(10) NOT NULL
    26. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    27.  
    28. --
    29. -- Дамп данных таблицы `link_post_tag`
    30. --
    31.  
    32. INSERT INTO `link_post_tag` (`post_id`, `tag_id`) VALUES
    33. (2, 1),
    34. (2, 2);
    35.  
    36. -- --------------------------------------------------------
    37.  
    38. --
    39. -- Структура таблицы `posts`
    40. --
    41.  
    42. CREATE TABLE `posts` (
    43.   `post_id` int(10) NOT NULL,
    44.   `subj` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
    45.   `body` text COLLATE utf8mb4_unicode_ci NOT NULL,
    46.   `author_id` int(11) NOT NULL
    47. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    48.  
    49. --
    50. -- Дамп данных таблицы `posts`
    51. --
    52.  
    53. INSERT INTO `posts` (`post_id`, `subj`, `body`, `author_id`) VALUES
    54. (2, 'сабж1', 'тест1', 1);
    55.  
    56. -- --------------------------------------------------------
    57.  
    58. --
    59. -- Структура таблицы `tags`
    60. --
    61.  
    62. CREATE TABLE `tags` (
    63.   `tag_id` int(10) NOT NULL,
    64.   `tag_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL
    65. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    66.  
    67. --
    68. -- Дамп данных таблицы `tags`
    69. --
    70.  
    71. INSERT INTO `tags` (`tag_id`, `tag_name`) VALUES
    72. (1, 'тег1'),
    73. (2, 'тег2');
    74.  
    75. --
    76. -- Индексы сохранённых таблиц
    77. --
    78.  
    79. --
    80. -- Индексы таблицы `link_post_tag`
    81. --
    82. ALTER TABLE `link_post_tag`
    83.   ADD KEY `post_id` (`post_id`),
    84.   ADD KEY `tag_id` (`tag_id`);
    85.  
    86. --
    87. -- Индексы таблицы `posts`
    88. --
    89. ALTER TABLE `posts`
    90.   ADD PRIMARY KEY (`post_id`);
    91.  
    92. --
    93. -- Индексы таблицы `tags`
    94. --
    95. ALTER TABLE `tags`
    96.   ADD PRIMARY KEY (`tag_id`),
    97.   ADD UNIQUE KEY `tag_name` (`tag_name`);
    98.  
    99. --
    100. -- AUTO_INCREMENT для сохранённых таблиц
    101. --
    102.  
    103. --
    104. -- AUTO_INCREMENT для таблицы `posts`
    105. --
    106. ALTER TABLE `posts`
    107.   MODIFY `post_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
    108. --
    109. -- AUTO_INCREMENT для таблицы `tags`
    110. --
    111. ALTER TABLE `tags`
    112.   MODIFY `tag_id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
    113. --
    114. -- Ограничения внешнего ключа сохраненных таблиц
    115. --
    116.  
    117. --
    118. -- Ограничения внешнего ключа таблицы `link_post_tag`
    119. --
    120. ALTER TABLE `link_post_tag`
    121.   ADD CONSTRAINT `post_id` FOREIGN KEY (`post_id`) REFERENCES `posts` (`post_id`) ON DELETE CASCADE ON UPDATE CASCADE,
    122.   ADD CONSTRAINT `tag_id` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`tag_id`) ON DELETE CASCADE ON UPDATE CASCADE;
     
    cadijob нравится это.
  11. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Извините что голову морочил... В одной таблицы был атрибут unsigned а у другой нет...
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    ну сделай у обоих ансигнед. Это просто числа с минусом могут быть или нет. Для индексов обычно все больше нуля идут, т.е. unsigned.
     
  13. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Все сделал. Спасибо.
     
  14. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    А в php вытаскивать как?
    PHP:
    1. ("SELECT * FROM `articlesTags`");
    А дальше, как связать все эти таблицы в php?
     
  15. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    в промежуточную таблицу делаете запрос и выбираете все теги которые закреплены за нужной страницей. а таблицу тегов в этом вопросе связываете с помощью JOIN..
     
  16. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Ну.. Вы наверное пошлёте меня в google(там я уже был), но можно по подробнее? Пусть пример будет на русском, всё равно.
     
  17. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    PHP:
    1. SELECT * FROM link AS l
    2. LEFT JOIN tags AS t ON(l.tag_id = t.tag_id)
    3. WHERE l.post_id = 5
    получите все теги для поста с id = 5
     
    cadijob нравится это.
  18. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Спасибо. Работает.
    Вот у меня теперь четыре функции: чтобы получить статьи и функцию вывода их в массив и для статьей с тегами тоже самое. Но что бы получить теги к каждой отдельной статье, а не в функции задавать её id, нужно объединить их? Или отправлять параметр из главной страницы в последнюю функцию и заносить его в WHERE l.post_id =5, вместо 5-ти параметр?
     
  19. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    сделайте просто функцию getTagByPostId($id) и получайте
     
  20. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    А где задавать $id и как получить данные поля из статьи? Если link это промежуточная таблица?
     
  21. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    1. Вы берете из базы статью - получаете ее ID
    2. Делаете запрос в промежуточную таблицу выбираете все строки у которых post_id равен id вашей статьи. вместе с этим потягиваете связи из таблицы тегов (JOIN)..
     
  22. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    index.php -
    PHP:
    1. $articles= getTagByPostId(getArticles());
    function.php(беру ID) -
    PHP:
    1. function getArticles(){
    2.     connectPDO();
    3.     global $pdo;
    4.     $articlesResult = $pdo->query("SELECT `id` FROM `article` ORDER BY `id`");
    5.     return resultToArrayArticle($articlesResult );
    6. }
    7. function resultToArrayArticle($articlesResult ){
    8.     $array = array();
    9.     while ($row = $articlesResult ->fetch( PDO::FETCH_ASSOC )){
    10.         $array[] = $row;
    11.     }
    12.     return $array;
    13. }
    запрос к промежуточной таблице -
    PHP:
    1. function getTagByPostId($articlesResult){
    2.     connectPDO();
    3.     global $pdo;
    4.     $TagByPostId = $pdo->query("SELECT * FROM `articleTags` AS l LEFT JOIN `tags` AS t ON(l.tagID = t.id) WHERE l.articleID = $articlesResult");
    5.     return resultToArrayArticle($TagByPostId);
    6. }
    7. function resultToArrayTagByPostId($TagByPostId){
    8.     $array = array();
    9.     while ($row = $TagByPostId->fetch( PDO::FETCH_ASSOC )){
    10.         $array[] = $row;
    11.     }
    12.     return $array;
    13. }
    Правильно начал?
     
  23. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    Код (Text):
    1.     $TagByPostId = $pdo->query("SELECT * FROM `articleTags` AS l LEFT JOIN `tags` AS t ON(l.tagID = t.id) WHERE l.articleID = $articlesResult");
    тут Вы в ID отправляете массив.. мускул Вас не поймет..
     
  24. cadijob

    cadijob Новичок

    С нами с:
    14 июл 2017
    Сообщения:
    35
    Симпатии:
    0
    Нужно что-то типа такого -
    PHP:
    1. foreach ($articlesResultas $key => $value) {
    2.              $TagByPostId = $pdo->query("SELECT * FROM `articleTags` AS l LEFT JOIN `tags` AS t ON(l.tagID = t.id) WHERE l.articleID = $key");
    3.     }
    ?
     
  25. Алекс8

    Алекс8 Активный пользователь

    С нами с:
    18 май 2017
    Сообщения:
    1.730
    Симпатии:
    359
    если Вам надо сразу для большого количество статей - то лучше не через цикл базу дергать, а через IN взять нужные записи а потом раскидать их куда надо..
    или можно через функцию мускула group_concat
     
    cadijob нравится это.