Есть несколько алгоритмов хранения деревьев в mysql, и мне кажется, что это в корне неправильно, так как реляционная база данных не предназначена для этого, а представление линейных структур данных в древовидную — один большой костыль в коде и понижение надёжности и скорости приложения. Как я задумался об использование NoSQL в частности mongoDB? Всё просто, меня на собеседование спросили:
Как построить дерево?
Я ответил:
Берём mongodb и документ с деревом из неё
Мне так и не перезвонили, но я не расстраиваюсь за то теперь я изучаю mongoDB и не люблю Mysql(к счастью или к сожалению я не знаю). В общем, разберём как всё это работает? На примере дерева комментариев написанном на php.
Сразу приведу код:
// метод для подключения к mongodb находиться в абстрактном классе // привожу его для понимания кода ниже /** * @return \MongoDB\Driver\Manager * */ static function getConnect() { if(!is_null(self::$_connect)) { return self::$_connect; } self::$_connect = new \MongoDB\Driver\Manager(Config_Db::getConf()['mongodb']['connect']); return self::$_connect; } // наш контроллер /** * add comment action */ public function addCommentAction() { $time = time(); // массив с данными комментария //insert new comment to the page $arrData = array( 'page' => $_POST['page_id'], // id страницы в mongo 'time' => $time, // время написания комментария 'name' => $_POST['name'], // имя написавшего 'comment' => $_POST['comment'] // сам комментрарий ); $connect = Core_Model_Mongo::getConnect(); // подключение к монгодб // две строки ниже подготовка к записи так как они не относятся к алгоритму // то в дальнейшем я не буду на них заострять внимание $write = new MongoDB\Driver\BulkWrite(); $writeConcern = new MongoDB\Driver\WriteConcern(MongoDB\Driver\WriteConcern::MAJORITY); // и так, если человек отвечает на чей-то комментарий, то к нам приходит reply с id комментария if(isset($_POST['reply']) && !empty($_POST['reply'])) { // id комментария $reply = $_POST['reply']; // путь для сохранения комментария // другими словами, это путь по которому будет сохранен комментарий $path = ''; if(isset($_POST['path']) && !empty($_POST['path'])) { $path = $_POST['path']; } else { $path = 'replies'; } // собственно, обновление данных по комментарию $write->update( array('_id' => new MongoDB\BSON\ObjectID($reply)), // загружаем комментарий array('$push' => array($path => $arrData) ) // делаем push, в существующие данные, относительно path ); } else { $write->insert($arrData); // если комментарий новый вставляем в базу } // запускаем запрос $connect->executeBulkWrite(Config_Db::getConf()['mongodb']['db'] . '.comments', $write, $writeConcern); // и возвращаемся обратно header('Location:' . $_POST['back_url']); }
И так в переменную path передаётся путь для сохранения, к примеру у нас в монго есть комментарий, представим его в виде ‘чистого’ массива, так как в реальности это массив объектов мы упростим всё до массива.
array ( 'name' => 'test', 'comment' => 'test comment', );
После update, с push и переменной path = ‘reply’, наш массив приобретёт вид:
array ( 'name' => 'test', 'comment' => 'test comment', 'reply' => array ( [0] => array( 'name' => 'test reply test' 'comment' => 'test comment reply' ) ) );
А если отвечать на вложенный комментарий, то путь приобретёт вид ‘reply.0.reply’, то есть в reply комментария взять 0 элемент, и вставить туда новое поле reply с данными, после операции мы получим следующий массив.
array ( 'name' => 'test', 'comment' => 'test comment', 'reply' => array ( [0] => array( 'name' => 'test reply test' 'comment' => 'test comment reply' 'reply' => array ( [0] => array( 'name' => 'test reply test' 'comment' => 'test comment reply' ) ) ) ) );
И это всё, весь алгоритм, просто вставить и потом просто взять этот массив для рендера таким какой он был, есть и будет. Рендер не буду расписывать так как рендер это не такая важная часть, да и я просто его делаю через print_r() шутка конечно, но принцип тот же… Спасибо за внимание дорогие хаброюзеры.
П.С.: В примере представлен алгоритм и в нём есть допущения, а именно отсутствие сортировки комментариев и её персистетности.
ссылка на оригинал статьи https://habrahabr.ru/post/279915/
Добавить комментарий