Модераторы: skyboy, MoLeX, Aliance, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Деревья Nested Sets, В одной таблице - хранить много деревьев 
:(
    Опции темы
Wowa
Дата 13.9.2005, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Хочу использовать алгоритм Nested Sets для построения дерева с неогр. вложеностью. Но система многопользовательская и каждый пользователь должен иметь возможность построить подобное дерево. Создавать на каждого юзера по таблице - не решение. Поэтому нужно хранить все деревья в одной таблице.
Если мысли, как это сделать?

Кто ничего не знает об этом алгоритме, можно коротко почитать тут: http://www.izone.kiev.ua/web/php/23.htm (вторая часть статьи)
PM WWW   Вверх
Bikutoru
Дата 13.9.2005, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлекающийся
**


Профиль
Группа: Участник
Сообщений: 522
Регистрация: 24.5.2005
Где: Москва

Репутация: 2
Всего: 22



Код

CREATE TABLE multiuser_tree
(
    id_node BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
    node_name VARCHAR(50) NOT NULL,
    num_children SMALLINT NOT NULL DEFAULT 0, #для ускорения работы
    fk_user INT UNSIGNED NOT NULL, #для разделения по пользователям
    fk_parent_node BIGINT UNSIGNED DEFAULT 0 NOT NULL, #для организации дерева, 0 - "корень"
    PRIMARY KEY(id_node),
    KEY(fk_parent_node),
    KEY(fk_user)
);

fk_user - какая-то характеристика пользователя. Если он(пользователь) должен быть зарегистрированным, то его id - самое оно, если же нет, то можно использовать идентификатор сессии.
Добавлено @ 13:35
Можно и еще упростить - сделать таблицу
Код

CREATE TABLE user_tree_root(
    fk_user INT NOT NULL PRIMARY KEY,
    fk_root INT NOT NULL REFERENCES multiuser_tree(id_node)
    UNIQUE(fk_root)
);

а из multiuser_tree fk_user выбросить. Тогда всё сводится к выборке корня и "хождению" по multiuser_tree. Если же пользователи уже описаны, то достаточно добавить в таблицу с их описанием один столбец.

Это сообщение отредактировал(а) Bikutoru - 13.9.2005, 13:30


--------------------
Человек, словно в зеркале мир — многолик, 
Он ничтожен — и он же безмерно велик!
Омар Хайям
PM   Вверх
Bikutoru
Дата 13.9.2005, 13:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлекающийся
**


Профиль
Группа: Участник
Сообщений: 522
Регистрация: 24.5.2005
Где: Москва

Репутация: 2
Всего: 22



Уппс. Это же не Nested Sets...


--------------------
Человек, словно в зеркале мир — многолик, 
Он ничтожен — и он же безмерно велик!
Омар Хайям
PM   Вверх
AntonioBanderaz
Дата 13.9.2005, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Да ничего сложного, делать узлом в руте как-бы пользователя, а все подузлы и листья, ет всё его, вывод такого дерева можно выполнить запросом...

Код

SELECT A.*, IF (A.cat_left+1 < A.cat_right, 1, 0) AS nflag FROM ".$tbl." A, ".$tbl." B WHERE B.cat_id='".$id."' AND A.cat_left >= B.cat_left AND A.cat_right <= B.cat_right ORDER BY A.cat_left"


где $tbl - таблица
$id - ну это элемент, для которого выводятся все дети, поддерево короче.
Добавлено @ 14:57
Забыл, если nflag = 1 - значит есть потомки.

Это сообщение отредактировал(а) AntonioBanderaz - 13.9.2005, 14:58


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Bikutoru
Дата 13.9.2005, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Увлекающийся
**


Профиль
Группа: Участник
Сообщений: 522
Регистрация: 24.5.2005
Где: Москва

Репутация: 2
Всего: 22



Кстати, нашёл очень хорошую статью об этом деле. Здесь


Это сообщение отредактировал(а) Bikutoru - 13.9.2005, 18:40


--------------------
Человек, словно в зеркале мир — многолик, 
Он ничтожен — и он же безмерно велик!
Омар Хайям
PM   Вверх
Wowa
Дата 13.9.2005, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 13.9.2005, 13:55)
Да ничего сложного, делать узлом в руте как-бы пользователя

Да, я тоже об этом думал... Но не знаю, насколько это хорошо, если пользователей несколько десятков тысяч будет. И каждый будет иметь в своем дереве примерно по 15 элементов, который в среднем на двух или трех уровнях вложенности располагаться будут.
PM WWW   Вверх
AntonioBanderaz
Дата 13.9.2005, 23:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



А думаешь при другой расстановке у тебя будет меньше елементов, как я понял, это для выборочного отображения форумов на сайте... =)) В принципе алгоритм хороший, только по изменениях какого-либо элемента придётся пересчитывать всё, что следует за ним, а вот это уже не есть гуд ( для базы в 10000 элементов ещё нормально, а 10000*15 - не пробовал, посмотри потести скорость)
Цитата(Wowa @ 13.9.2005, 19:26)
который в среднем на двух или трех уровнях вложенности располагаться будут.

А вот это всё равно, какая у них вложеность, хоть 1999-ая создай дополнительное поле level, это будет быстрее работать, чем делать пересчёт по всем границам ветвей.

У меня такие поля в БД.
ID | cat_left | cat_right | cat_level [name .... description]
Из них рабочие первые четыре, остальные информационные...


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 13.9.2005, 23:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 13.9.2005, 22:18)
А думаешь при другой расстановке у тебя будет меньше елементов, как я понял, это для выборочного отображения форумов на сайте... =))

нет, совсем не для этого...


Цитата(AntonioBanderaz @ 13.9.2005, 22:18)
В принципе алгоритм хороший, только по изменениях какого-либо элемента придётся пересчитывать всё, что следует за ним, а вот это уже не есть гуд ( для базы в 10000 элементов ещё нормально, а 10000*15 - не пробовал, посмотри потести скорость)

Если у меня есть три корневых раздела, и я добавляю во второй корневой раздел еще одну ветку. Будут ли затронуты как-то первый и третий разделы? Ничего там пересчитываться не будет?
PM WWW   Вверх
AntonioBanderaz
Дата 14.9.2005, 02:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 13.9.2005, 23:51)
Если у меня есть три корневых раздела, и я добавляю во второй корневой раздел еще одну ветку. Будут ли затронуты как-то первый и третий разделы? Ничего там пересчитываться не будет?

Только третий и общий корень, поле right. Да у третьего, ко всем полям, имею ввиду right и left, будет прибавлена 2.


Я тут накотал классик для себя, думаю тебе это подойдёт.
Класс DB нужен для работы с базой данных:
Код

<?php
class DB {
 var $host = '';
 var $user = '';
 var $password = '';
 var $database = '';
 var $presistent = false;
 
 var $conn = null;
 
 var $result = false;
 
 function DB($host, $user, $password, $database, $persistent = false) {
      $this->host = $host;
      $this->user = $user;
      $this->password = $password;
      $this->database = $database;
      $this->presistent = $presistent; 
 }
 function open() {
      $this->presistent ? $func = 'mysql_pconnect' : $func = 'mysql_connect';
      $this->conn = $func($this->host, $this->user, $this->password);
      if(!$this->conn) return false;
      if(!@mysql_select_db($this->database, $this->conn) return false;
      return true;
 }
 function close() {
      return(@mysql_close($this->conn));
 }
 function error() {
      return(mysql_error());
 }
 function query($sql) {
      $this->result = @mysql_query($sql, $this->conn);
      return($this->result != false);
 }
 function affectedRows() {
      return(@mysql_affected_rows($this->conn));
 }
 function numRows() {
      return(@mysql_num_rows($this->result));
 }
 function fetchObject() {
      return(@mysql_fetch_object($this->conn, MYSQL_ASSOC));
 }
 function fetchArray() {
      return(@mysql_fetch_array($this->conn, MYSQL_NUM));
 }
 function fetchAssoc() {
      return(@mysql_fetch_assoc($this->conn));
 }
 function freeResult() {
      return(@mysql_free_result($this->result));
 }
}
?>


А это уже для работы с деревьями для пользователя.
Код

<?php
class UsersTree {
 var $userId = 0;
 var $userExists = false;
 var $DB;

      function UsersTree($userId,$DB) {
       $this->DB = $DB;
       $this->DB->query("SELECT * FROM users WHERE id='$userId'");
       if($this->$DB->numRows() == 1) {
            $this->userExists = true; 
            $this->$userId = $userId; 
       }
       return $this->userExists;
      }
      function getUserTree() {
       if($this->userId && $this->userExists) {
            $query = "SELECT A.*, IF (A.left+1 < A.right, 1, 0) AS childExists FROM usersTree A, usersTree  B WHERE B.id='".$id."' AND A.left >= B.left AND A.cat_right <= B.right ORDER BY A.left";
            $this->DB->query($query);
            $returns = array();
            while($node = $this->DB->fetchAssoc()) {
                  $returns[] = $node;
            }
            return $returns; 
       } else return;
      }
      function getNodeInfo($id) {
       if($this->userId && $this->userExists) {
            $this->DB->query("SELECT left,right FROM userTree WHERE id=".$this->userId);
            $LR = $this->DB->fetchObject();
            $left = $LR->left;
            $right = $LR->right;
            if($id < $right && $id > $left) {
                  $this->DB->query("SELECT left,right,level FROM userTree WHERE id=$id"); 
                  return $this->DB->fetchObject();
            } else return;
       } else return;     
      }
      function insertUserNode($id,$array) {
       if($this->userId && $this->userExists && is_array($array) && $nodeInfo = $this->getNodeInfo($id)) {
            $nodeNames = implode(',', array_keys($data)).',';
            $nodeValues = "'".implode("','", array_values($data))."',";
            $nodeNames .= 'left,right,level';
       $nodeValues .= ($nodeInfo->right).','.($nodeInfo->right+1).','.($nodeInfo->level+1);
       $query = 'UPDATE userTree SET left=IF(left>'.$nodeInfo->right.',left+2,left), right=IF(right>='.$nodeInfo->right.',right+2,right) WHERE right>='.$nodeInfo->right;
       $this->DB->query($query);
       $query = 'INSERT INTO userTree('.$nodeNames.') VALUES('.$nodeValues.')';
       return $this->DB->query($query);
       } else return;
      }
      function deleteUserNode($id) {
        if($this->userId && $this->userExists  && $nodeInfo = $this->getNodeInfo($id)) {
            $query = 'DELETE FROM userTree WHERE id='.$id;
            $this->DB->query($query);
            $query = 'UPDATE userTree SET left=IF(left BETWEEN '.$nodeInfo->left.' AND '.$nodeInfo->right.',left-1,left),right=IF(right BETWEEN '.$nodeInfo->left.' AND '.$nodeInfo->right.',right-1,right),'
            .'level=IF(left BETWEEN '.$nodeInfo->left.' AND '.$nodeInfo->right.',level-1,level),left=IF(left >'.$nodeInfo->right.',left-2,left),'
            .'right=IF(right >'.$nodeInfo->right.',right-2,right) WHERE '.$this->right.'>'.$nodeInfo->left;
       return $this->DB->query($query);
        } else return;
      }
      function updateUserNode($id,$array) {
        if($this->userId && $this->userExists &&is_array($array) && $this->getNodeInfo($id)) {
            $query = '';
            foreach($array as $nodeName=>$nodeValue) {
                  $query .= ','.$nodeName."='".addslashes($nodeValue)."'";
            }
            return $this->DB->query("UPDATE userTree SET ".substr($sql_set,1)." WHERE id=$id");
            
        } else return;
      }
}
?>


Там могут быть маленькие ошибки, и не сделал обработку ошибок. Таблица и названия полей зашиты в запросы, надо в коде менять.. Во втором классе DB - ссылка на экземпляр первого класса. Надеюсь пригодится... =))) smile smile smile [b][/b]

Это сообщение отредактировал(а) AntonioBanderaz - 14.9.2005, 02:42


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
AntonioBanderaz
Дата 14.9.2005, 02:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Да кстате у всего должен быть общий корень, один, а не три или больше... smile


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 20.9.2005, 20:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 14.9.2005, 01:46)
Да кстате у всего должен быть общий корень, один, а не три или больше... 

Нет. Я подумал и решил, что так не годится. Для каждого юзера нужно обязательно отдельное дерево не связанное с другими. Т.к. иначе, если вдруг дерево запорится у кого-то, то может быть такое, что и у других что-то поломается.
PM WWW   Вверх
Wowa
Дата 20.9.2005, 20:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Если делать так, чтобы с корня выходило много веток и у каждого юзера было бы по своей ветке. То сюдя из этого:
--Resize_Images_Alt_Text--

насколько я понял, если какой-то юзер что-то добавит в своей ветке, то должны будут пересчитаться ключи у всех веток других юзеров, если они "правее". Что совершенно недопустимо и глупо при большом кол-ве юзеров.


PM WWW   Вверх
Wowa
Дата 20.9.2005, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Я решил все-таки использовать метод Adjacency List, т.к. уровней вложенности всего 3-4 будет.
PM WWW   Вверх
AntonioBanderaz
Дата 20.9.2005, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 20.9.2005, 20:18)
Нет. Я подумал и решил, что так не годится. Для каждого юзера нужно обязательно отдельное дерево не связанное с другими. Т.к. иначе, если вдруг дерево запорится у кого-то, то может быть такое, что и у других что-то поломается.

Ну это врятли, деревья по сути между собой не связяны, если только оболочкой (root'ом);

Цитата(Wowa @ 20.9.2005, 21:35)
Я решил все-таки использовать метод Adjacency List, т.к. уровней вложенности всего 3-4 будет.

Напиши по-подробней про него.


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 20.9.2005, 23:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 20.9.2005, 22:35)

Ну это врятли, деревья по сути между собой не связяны, если только оболочкой (root'ом);

Как это не связаны? По рисунку, который я выше прикрепил - видно, что если я в первой ветке выходящей с корня что-то изменю(например, добавлю еще один уровень), то во второй и третьей ветках выходящих с корня - должны быть пересчитаны left key и right key.


Цитата(AntonioBanderaz @ 20.9.2005, 22:35)

Напиши по-подробней про него.

Adjacency List - и есть именно простейший метод хранения деревьях, который ПЕРВЫМ описан в статье, ссылку на которую я привел выше.
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 20.9.2005, 23:45)
Adjacency List - и есть именно простейший метод хранения деревьях, который ПЕРВЫМ описан в статье, ссылку на которую я привел выше.
Всё ясно. Только обход долгий.

Цитата(Wowa @ 20.9.2005, 23:45)
Как это не связаны? По рисунку, который я выше прикрепил - видно, что если я в первой ветке выходящей с корня что-то изменю(например, добавлю еще один уровень), то во второй и третьей ветках выходящих с корня - должны быть пересчитаны left key и right key.
Дык это я тебе и писал... Я имею ввиду не связаны на прямую, т.е если какое дерево просто убрать, то остальные не "поломаются" smile
Ты боишься если какая ошибка может произойти, так можно при изменениях использовать трансакции, или тоже не подходит?


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 20.9.2005, 23:02)
Ты боишься если какая ошибка может произойти, так можно при изменениях использовать трансакции, или тоже не подходит?

Можно... но для такой просто операции использовать трансакции - как-то странно. Итак должно чики-пики работать smile


Цитата(AntonioBanderaz @ 20.9.2005, 23:02)
Я имею ввиду не связаны на прямую, т.е если какое дерево просто убрать, то остальные не "поломаются"

Представь. 10 000 юзеров. У каждого в базе хранится по дереву с несколькими ветками. Какой-то юзер с первой ветки решает добавить себе подветку, теперь должны перестраиваться параметры веток у всех других юзеров.
Добавлено @ 00:08
Цитата(AntonioBanderaz @ 20.9.2005, 23:02)
Всё ясно. Только обход долгий.

Да, долгий вероятно. Зависит от ситуации. Но если уровней вложенности мало и веток немного, то спокойно можно даже всё дерево выбрать и быстренько в памяти выстроить нить из родителей. Ну или же рекурсией выбирать через запросы к базе..
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 21.9.2005, 00:06)
Представь. 10 000 юзеров. У каждого в базе хранится по дереву с несколькими ветками. Какой-то юзер с первой ветки решает добавить себе подветку, теперь должны перестраиваться параметры веток у всех других юзеров.


Да это будет долговато, даже если поля leftKey и RightKey сделать, извиняюсь за мой плохой английский, "проидексировать", короче в мускуле есть что-то на полобие "register " в С. Только точно не помню как это называется. Скорость увеличится, но думаю не очень на много...

Про nested можно сделать разряженное дерево, т.е. с запасом для каждого юзера. Т.е ограничить по кол-ву элементов, И все которые не заданы им, оставлять пустыми и их просто не выводить... А когда добовляет то менять только в области самого юзера.
Добавлено @ 00:20
Цитата(Wowa @ 21.9.2005, 00:06)
Да, долгий вероятно. Зависит от ситуации. Но если уровней вложенности мало и веток немного, то спокойно можно даже всё дерево выбрать и быстренько в памяти выстроить нить из родителей. Ну или же рекурсией выбирать через запросы к базе..

Я считаю нужно сделать двумя способами, и проверить скорость!! Так думаю правильней будет.


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 20.9.2005, 23:15)
Про nested можно сделать разряженное дерево, т.е. с запасом для каждого юзера. Т.е ограничить по кол-ву элементов, И все которые не заданы им, оставлять пустыми и их просто не выводить... А когда добовляет то менять только в области самого юзера.

Можно, но не стандартными средствами класса. А писать свой или переделывать для этого существующий - долго.

Или у тебя есть что-то готовое для этого?
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 00:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 21.9.2005, 00:24)
Или у тебя есть что-то готовое для этого?

Готового нет, только родил идею smile
Я могу посидеть завтра может что и накатаю. smile
Цитата(Wowa @ 21.9.2005, 00:24)
Можно, но не стандартными средствами класса. А писать свой или переделывать для этого существующий - долго.

На самом деле не так уж и долго, может часа 4 + отладка час/полтора. Вот то что сверху для юзеров можно за основу взять, а там в основном запросы и вывод в массив поменять надо, наверно ещё привязку к таблице пользователей надо убрать. (был написан за 1 час)


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 20.9.2005, 23:30)
Вот то что сверху для юзеров можно за основу взять

Наверное лучше за основу взять этот: http://dev.e-taller.net/dbtree
Т.к. он более функционален
Добавлено @ 00:40
Цитата(AntonioBanderaz @ 20.9.2005, 23:15)
Про nested можно сделать разряженное дерево, т.е. с запасом для каждого юзера.

Интересно, какой запас надо делать. По идее - должно быть практически все равно какой запас делать. Можно по сотке оставлять..

PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 21.9.2005, 00:39)
Интересно, какой запас надо делать. По идее - должно быть практически все равно какой запас делать.

В принципе любой, ты сам определишь какой, т.е это вроде максимума элементов дерева...

Цитата(Wowa @ 21.9.2005, 00:06)
Да, долгий вероятно. Зависит от ситуации. Но если уровней вложенности мало и веток немного, то спокойно можно даже всё дерево выбрать и быстренько в памяти выстроить нить из родителей. Ну или же рекурсией выбирать через запросы к базе..



Вот блин делема, либо быстрый вывод и долгое изменение, либо быстрое изменение и долгий вывод...

как бы найти оптимальное... ???

Код

if((aloritm = LongOut.QuickModify) || (algoritm = LongModify.QuickOut)) 
        algoritm = чтож здесь поставить?

Добавлено @ 00:50
Цитата(AntonioBanderaz @ 21.9.2005, 00:49)
В принципе любой, ты сам определишь какой, т.е это вроде максимума элементов дерева...
Эт для пользователя.



--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 00:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



AntonioBanderaz вот тут есть обсуждение на эту тему: http://www.phpclub.ru/talk/showthread.php?s=&threadid=48194

Не все так просто. Как переносить при этом ветки с подветками?
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 01:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Интересненько... Да, оказалось не всё так просто...

Цитата(Wowa @ 21.9.2005, 00:57)
Не все так просто. Как переносить при этом ветки с подветками?

Вот это вообще не представляю... Ели только сначала удалять запас, перемещать, а потом весь запас дополнять, но это уже совсем через ЖЖЖ.
Добавлено @ 01:15
http://www.profy.net/forum/view_topic/35.html - вот тут почитай.


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
AntonioBanderaz
  Дата 21.9.2005, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Нашёл подходящий тебе.
вот документация
Код

An object to abstact away from the flat data representation forced by relational databases when willing to represent
 hierarchical data. This object makes use of both, tree traversal and the adjacency methods.

Examples
I presume you have a table in your database with the following SQL parameters

CREATE TABLE tree (
id int(12) NOT NULL AUTO_INCREMENT,
parent int(12),
title varchar(255) NOT NULL default 'no title',
lft INTEGER UNSIGNED NOT NULL default '0',
rgt INTEGER UNSIGNED NOT NULL default '0',
PRIMARY KEY  (id),
KEY rgt (rgt),
KEY lft (lft),
KEY parent (parent)
);

Hence create an instance of this object:

$myTree = new traversedTree($db);

Then add some data using:

$myTree->add(); //creates the root node

$myTree->add(0); //adds a node as child of root node

$myTree->add(0); //adds another node as child of root node

Then fetch the data and display the data:

$tree = $myTree->getTree();

foreach($tree as $leaf){ echo str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;",$leaf['offset']) . $leaf['title'] . "<br>"; }


Добавлено @ 01:24
А вот и полная.
http://www.inses.ru/lj/tree/

Код

CREATE TABLE tree (
id int(12) NOT NULL AUTO_INCREMENT,
parent int(12),
title varchar(255) NOT NULL default 'no title',
lft INTEGER UNSIGNED NOT NULL default '0',
rgt INTEGER UNSIGNED NOT NULL default '0',
PRIMARY KEY  (id),
KEY rgt (rgt),
KEY lft (lft),
KEY parent (parent)
);


А как всё просто оказалось!!!! Блин -)) Даже обидно, что не додумался....

вот типо сам код smile

Это сообщение отредактировал(а) AntonioBanderaz - 21.9.2005, 01:28

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  treebrowser.zip 40,45 Kb


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
AntonioBanderaz
Дата 21.9.2005, 01:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



http://www.sitepoint.com/print/1105/ - тут тоже кое что интересное.


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 01:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 21.9.2005, 00:21)
Нашёл подходящий тебе.
вот документация


А как он мне может помочь?
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 01:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Ну это что-то среднее между Nested и списком. Короче будет оптимально его использовать для твоей задачи...
У тебя теперь есть три варианта которые Ты можешь потестить и выбрать самый оптимальный.

Посмотри на организацию таблицы.

Это сообщение отредактировал(а) AntonioBanderaz - 21.9.2005, 01:47


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Gold Dragon
Дата 21.9.2005, 08:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Призрачный
****


Профиль
Группа: Экс. модератор
Сообщений: 6753
Регистрация: 1.3.2004
Где: Россия, Тамбов

Репутация: 2
Всего: 71



Не знаю на сколько это в тему, но вдруг. В своё время я мучился над генеологическим деревом и как присвоить уникальный номер человеку в этом дереве.

Ниже прикрепил рисунок простого дерева. Поясню.
- Есть уровни родства, их здесь 4
- Есть группы родства, в которые входят братья и сёстра
- В каждой группе есть определённый человек

И от сюда можно описать любого человека, например выделенного зелёным - 2.1.2. Во-первых получается уникальный номер. Во-вторых, легко можно найти этого человека в древе и все его связи не зависимо от сложности родства и самого древа.

Я понимаю, что это немного не то, но мало ли smile

Присоединённый файл ( Кол-во скачиваний: 7 )
Присоединённый файл  tree.gif 11,39 Kb


--------------------
Нельзя жить в прошлом, оно уже прошло.
Нельзя жить в будущем, оно ещё не наступило.
Нужно жить в настоящем, помня прошлое и думая о будущем!
PM MAIL WWW ICQ   Вверх
AntonioBanderaz
Дата 21.9.2005, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Поставлю задачу - локализовать дерево.
Как я понимаю, нужно сделать список деревьев, по которым можно проходить уже созданым алгоритмом.
Надо придумать как индотифицировать само дерево, можно и лучше эт будет делать в другой таблице.
Теперь у нас две таблицы, одна с деревьями, другая со списком.
Теперь появляются проблемы, как быть с перемещением дерева, точнее, как это локально организовать.
Как тоже локально добовлять в дерево, чтобы изменялось только локальное дерево.

Вот собственно и задача...



--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 21:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Вот тут есть хорошая статья по работе с деревьями:
http://www.evolt.org/article/Four_ways_to_...4047/index.html
Добавлено @ 21:16
traversedTree Object v. 1.12 - видимо как раз то, что мне нужно. Интересно только, насколько качественно написан этот класс.. И нет ли в нем глюков. Сейчас буду смотреть..
PM WWW   Вверх
AntonioBanderaz
Дата 21.9.2005, 21:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 21.9.2005, 21:12)
traversedTree Object v. 1.12 - видимо как раз то, что мне нужно. Интересно только, насколько качественно написан этот класс.. И нет ли в нем глюков. Сейчас буду смотреть..

Всё таки решил его использовать? smile smile

По поводу локализации. Объясняю можно ведь использовать nested деревья, только нало сделать возможность управление локальным деревом. Т.е. в некоторой таблице лежит куча так сказать root'ов, по которым нам не пройтись уже существующим классом, ошибку выдаст. А вот если можно будет локализовать дерево, тоесть получать доступ к нему по id его root'а. Грубо говоря в таблице хранится как-бы массив деревьев, и нам нужно обращаться к отдельным его елементам не вызывая изменений в остальных елементах.

Вот для этого нам и нужна вторая таблица, чтобы знать сколько у нас деревьев, какой у них id и индефикатор.


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 21.9.2005, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 21.9.2005, 20:32)
По поводу локализации. Объясняю можно ведь использовать nested деревья, только нало сделать возможность управление локальным деревом. Т.е. в некоторой таблице лежит куча так сказать root'ов, по которым нам не пройтись уже существующим классом, ошибку выдаст. А вот если можно будет локализовать дерево, тоесть получать доступ к нему по id его root'а. Грубо говоря в таблице хранится как-бы массив деревьев, и нам нужно обращаться к отдельным его елементам не вызывая изменений в остальных елементах.

Вот для этого нам и нужна вторая таблица, чтобы знать сколько у нас деревьев, какой у них id и индефикатор.

Но ведь при этом мы не уйдем от того, что будут перестраиваться значения столбцов left, right в соседних ветках, которые другим юзерам принадлежать будут.
Добавлено @ 22:47
Цитата(AntonioBanderaz @ 21.9.2005, 20:32)
Всё таки решил его использовать?

не знаю, я пока изучаю класс.

Насколько я понял, то там разделять деревья для разных юзеров нужно путем создания еще одного столбца в ИД юзера, и потом в через setCondition() прописывать доп. условия, чтобы выбирались, обновлялись, удалялись ветки только с опред. юзером. Иначе имхо никак.

Не понял, для чего там:
var $limitStart;// SQL Limit clause @access private
var $limitSet; // SQL Limit clause @access private


PM WWW   Вверх
Wowa
Дата 22.9.2005, 02:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290




В общем я решил пойти следующим способом...
1. Использовать Nested Sets
2. Использоваться класс phpDBTree 1.4 для работы с ним.
4. Парсить все запросы к дереву, добавляя к ним WHERE owner=ИД
5. Таким образом я собираюсь хранить в одной таблице довольно простные деревья нескольких десятков юзеров

Что скажете?



PM WWW   Вверх
AntonioBanderaz
Дата 22.9.2005, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Цитата(Wowa @ 21.9.2005, 22:41)
Но ведь при этом мы не уйдем от того, что будут перестраиваться значения столбцов left, right в соседних ветках, которые другим юзерам принадлежать будут.

Я же написал, надо локализовать, т.е не чтобы не затрагивало ничего в других элементах.


А вот списки тебе совсем не подходят... На 10000 - они могут из-за рекурсии и большого числа запросов повесить сервис. !!!!
Добавлено @ 07:48
Цитата(Wowa @ 22.9.2005, 02:26)
4. Парсить все запросы к дереву, добавляя к ним WHERE owner=ИД

Объясни по-подробнее


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 22.9.2005, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Цитата(AntonioBanderaz @ 22.9.2005, 06:47)
Объясни по-подробнее

Ну, есть обычный класс для работы с этим дереревом. У каждой ветки будет значение owner, которое означает, какому юзеру принадлежит эта ветка. Получается, что мы можем добавляя ко всем запросам WHERE owner=ИД ЮЗЕРА, работать в одной таблице с множеством деревьев. По одному дереву на юзера. Деревья как раз между собой будут через owner различаться.

Добавлено @ 10:21
Цитата(AntonioBanderaz @ 22.9.2005, 06:47)
Я же написал, надо локализовать, т.е не чтобы не затрагивало ничего в других элементах.

Это ясно, что надо, но я все равно не понял твою логику.
PM WWW   Вверх
AntonioBanderaz
Дата 22.9.2005, 19:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Ну смотри у нас нет общего дерева, а куча так сказать root'ов в таблице, там могут быть одинаковые элементы с одинаковыми left и right, значит они могут в принципе подходить к любому из деревьев. Чтобы этого не было надо добавить индетификатор дерева, а дальше работать с существующим алгоритмом, только добовлять where tree_id='индетификатор'. А в другой таблице хранить "адреса" корней деревьев, с их индетификаторами. Ну вот как-то так smile


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Wowa
Дата 22.9.2005, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
Group Icon


Профиль
Группа: Админ
Сообщений: 15017
Регистрация: 14.9.2000
Где: Винград

Репутация: нет
Всего: 290



Да, так я и делаю smile
PM WWW   Вверх
AntonioBanderaz
Дата 22.9.2005, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Velichko Anton
**


Профиль
Группа: Участник
Сообщений: 851
Регистрация: 28.4.2005
Где: Санкт-Петербург

Репутация: 2
Всего: 18



Ну наконец пришли к общему так сказать знаменателю. Когда закончишь, выложи глянуть smile
Добавлено @ 22:43
Ну наконец пришли к общему так сказать знаменателю. Когда закончишь, выложи глянуть smile


--------------------
ГЫ... 
PM MAIL ICQ   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Базы Данных | Следующая тема »


 




[ Время генерации скрипта: 0.0872 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.