2011-07-23 12 views
26

quiero almacenar los directorios presentes en el disco en una base de datos manteniendo su estructura jerárquica/de árbol.base de datos jerárquica/de árbol para directorios en el sistema de archivos

Aquí es un higo,

 
         (ROOT) 
        /  \ 
        Dir2  Dir3 
       / \   \ 
       Dir4 Dir5  Dir6 
       /   
       Dir7 

estoy usando la base de datos SQLite .

  • Por favor sugiérame la consulta sql para almacenar la estructura anterior en la base de datos SQLite.

  • y una consulta para recuperar la ruta completa del directorio cuando selecciono uno.

es decir Supongamos selecciono Dir6 entonces i Sould obtener la ruta completa como ROOT/Dir2/dir3/dir7

+1

Una mesa de cierre podría ser una buena opción. Eche un vistazo a [¿Cuál es la forma más eficiente/elegante de analizar una tabla plana en un árbol?] (Http://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way- to-parse-a-flat-table-into-a-tree # 192462), y también vea [Bill Karwin's] (http://stackoverflow.com/users/20860/bill-karwin) diapositivas en [Modelos para datos jerárquicos ] (http://www.slideshare.net/billkarwin/models-for-hierarchical-data) – Mike

+0

El tema volvió a aparecer en la lista de mantenimiento de SQLite, y Eduardo Morras (re) señaló esta extensión de SQLble vtable para tratar con la jerarquía del repositorio de SQLite mismo: 1) http://www.sqlite.org/src/artifact/636024302cde41b2bf0c542f81c40c624cfb7012 2) http://www.sqlite.org/src/finfo?name=ext/misc/closure.c – ddevienne

Respuesta

32

Aquí hay un ejemplo de tabla de cierre rápido para SQLite. No he incluido las declaraciones para insertar elementos en un árbol existente. En cambio, acabo de crear las declaraciones de forma manual. Puede encontrar las instrucciones de inserción y eliminación en las diapositivas Models for hierarchical data.

Por el bien de mi cordura al insertar las identificaciones de los directorios, Retitulé los directorios para que coincida con sus IDs:

 (ROOT) 
    /  \ 
    Dir2  Dir3 
    / \   \ 
    Dir4 Dir5  Dir6 
/   
Dir7 

Crear tablas

CREATE TABLE `filesystem` (
    `id` INTEGER, 
    `dirname` TEXT, 
    PRIMARY KEY (`id`) 
); 

CREATE TABLE `tree_path` (
    `ancestor` INTEGER, 
    `descendant` INTEGER, 
    PRIMARY KEY (`ancestor`, `descendant`) 
); 

directorios Insertar en filesystem tabla

INSERT INTO filesystem (id, dirname) VALUES (1, 'ROOT'); 
INSERT INTO filesystem (id, dirname) VALUES (2, 'Dir2'); 
INSERT INTO filesystem (id, dirname) VALUES (3, 'Dir3'); 
INSERT INTO filesystem (id, dirname) VALUES (4, 'Dir4'); 
INSERT INTO filesystem (id, dirname) VALUES (5, 'Dir5'); 
INSERT INTO filesystem (id, dirname) VALUES (6, 'Dir6'); 
INSERT INTO filesystem (id, dirname) VALUES (7, 'Dir7'); 

Crear los caminos de mesa de cierre

INSERT INTO tree_path (ancestor, descendant) VALUES (1, 1); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 2); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 3); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 4); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 5); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 6); 
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 7); 
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 2); 
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 4); 
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 5); 
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 7); 
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 3); 
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 6); 
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 4); 
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 7); 
INSERT INTO tree_path (ancestor, descendant) VALUES (5, 5); 
INSERT INTO tree_path (ancestor, descendant) VALUES (6, 6); 
INSERT INTO tree_path (ancestor, descendant) VALUES (7, 7); 

ejecutar algunas consultas

# (ROOT) and subdirectories 
SELECT f.id, f.dirname FROM filesystem f 
    JOIN tree_path t 
    ON t.descendant = f.id 
WHERE t.ancestor = 1; 

+----+---------+ 
| id | dirname | 
+----+---------+ 
| 1 | ROOT | 
| 2 | Dir2 | 
| 3 | Dir3 | 
| 4 | Dir4 | 
| 5 | Dir5 | 
| 6 | Dir6 | 
| 7 | Dir7 | 
+----+---------+ 


# Dir3 and subdirectories 
SELECT f.id, f.dirname 
    FROM filesystem f 
    JOIN tree_path t 
    ON t.descendant = f.id 
WHERE t.ancestor = 3; 

+----+---------+ 
| id | dirname | 
+----+---------+ 
| 3 | Dir3 | 
| 6 | Dir6 | 
+----+---------+ 

# Dir5 and parent directories 
SELECT f.id, f.dirname 
    FROM filesystem f 
    JOIN tree_path t 
    ON t.ancestor = f.id 
WHERE t.descendant = 5; 

+----+---------+ 
| id | dirname | 
+----+---------+ 
| 1 | ROOT | 
| 2 | Dir2 | 
| 5 | Dir5 | 
+----+---------+ 

# Dir7 and parent directories 
SELECT f.id, f.dirname 
    FROM filesystem f 
    JOIN tree_path t 
    ON t.ancestor = f.id 
WHERE t.descendant = 7; 

+----+---------+ 
| id | dirname | 
+----+---------+ 
| 1 | ROOT | 
| 2 | Dir2 | 
| 4 | Dir4 | 
| 7 | Dir7 | 
+----+---------+ 

SELECT f.id, f.dirname 
    FROM filesystem f 
    JOIN tree_path t 
    ON t.ancestor = f.id 
WHERE t.descendant = (
SELECT id 
    FROM filesystem 
WHERE dirname LIKE '%7%' 
); 

+----+---------+ 
| id | dirname | 
+----+---------+ 
| 1 | ROOT | 
| 2 | Dir2 | 
| 4 | Dir4 | 
| 7 | Dir7 | 
+----+---------+ 
+0

@ JOHN: Lo siento, pero nunca he usado orientDB, así que no pude comentar. – Mike

+0

@JOHN: No estoy seguro de lo que quieres decir, por favor, ¿puedes dar un ejemplo? – Mike

+0

@JOHN: Hay algunas maneras de hacerlo. He agregado otro ejemplo que simplemente hace un SELECCIONAR adicional para encontrar el ID. También podrías hacer un JOIN. – Mike

1

Usted representa datos jerárquicos como una serie de nodos cada uno de los cuales tiene un ID y un ID de Padres . Se podría almacenar su en una tabla llamada DIRTAB con 2 columnas ID y una para el texto del nombre del directorio individuo:

ID -- as a primary key 
PARENT_ID -- refers to the ID of the parent row in DIRTAB 
DIRNAME -- the text of the name eg Dir5 

SQLite carece de la CONNECT BY que Oracle tiene que procesar los datos jerárquicos, pero creo que si 're preparado para aceptar un cierto SQL feo se puede aproximar algo jerárquica:

SELECT (CASE WHEN p5.DIRNAME IS NOT NULL THEN p5.DIRNAME || '/' ELSE '' END) || 
     (CASE WHEN p4.DIRNAME IS NOT NULL THEN p4.DIRNAME || '/' ELSE '' END) || 
     (CASE WHEN p3.DIRNAME IS NOT NULL THEN p3.DIRNAME || '/' ELSE '' END) || 
     (CASE WHEN p2.DIRNAME IS NOT NULL THEN p2.DIRNAME || '/' ELSE '' END) || 
     (CASE WHEN p1.DIRNAME IS NOT NULL THEN p1.DIRNAME || '/' ELSE '' END) || 
     p0.DIRNAME as FULLPATH 
FROM DIRTAB p0 
    LEFT OUTER JOIN DIRTAB p1 ON p1.ID = p0.PARENT_ID 
    LEFT OUTER JOIN DIRTAB p2 ON p2.ID = p1.PARENT_ID 
    LEFT OUTER JOIN DIRTAB p3 ON p3.ID = p2.PARENT_ID 
    LEFT OUTER JOIN DIRTAB p4 ON p4.ID = p3.PARENT_ID 
    LEFT OUTER JOIN DIRTAB p5 ON p5.ID = p4.PARENT_ID 
WHERE p0.DIRNAME = 'Dir6' 

el problema aquí es que usted tiene que anticipar la profundidad máxima de que la estructura de directorios y ampliar la instrucción SQL para hacer frente. He hecho 6 niveles como un ejemplo.
También asumo que SQLite no tiene problemas para concatenar cadenas vacías. (Algunos DB los tratan como nulos y convierten el resultado de la expresión completa en nulo)

1

Creo que deberías leer sobre un método caled Modified Preordenes árbol Transversal: http://www.sitepoint.com/hierarchical-data-database/

Ese enlace analiza dos métodos para s torrente de datos jerárquicos en bases de datos relacionales: el modelo de lista de adyacencia y el algoritmo de recorrido de árbol de preordenamiento modificado.

La idea principal del método Preordenes Árbol de recorrido modificado es anotar todos los nodos con los punteros a auxiliate la navegación y sub-árbol de selección: enter image description here

Cuestiones relacionadas