Cita:
Iniciado por estebanpixel el campo se llamaba child
La pregunta, en su formulación más genérica, es: cómo crear y mantener estructuras en árbol, sobre un almacenamiento basado en filas?
El sistema de "child" (más bien, "parent"), es la forma más sencilla, y "formal" de hacerlo,desde un punto de vista de estructura de la base de datos. Pero es importante pensar en todos los puntos de vista.Sobre todo, en cómo se va a acceder a los datos.
Supongamos que tienes un id de aquello sobre lo que se hacen comentarios (noticia, post de un blog, etc). Cómo obtienes sus comentarios?
- Caso 1:
La tabla "comentarios" tiene un campo "padre", y un campo "objetoComentado".
Los comentarios iniciales (que no son "respuesta"), tienen "padre" a NULL, y "objetoComentado" al id del objeto.
Los comentarios respuesta, tienen "padre" al id de comentario correspondiente, y "objetoComentado" al id del objeto.
Primera forma de acceder a los datos:
- Se obtienen todos los comentarios con padre==NULL.
- Por cada uno de ellos, recursivamente, se pregunta por comentarios respuesta.
Cuántas queries hacen falta ?:
1 para obtener los comentarios padre.
N, por cada uno de los anteriores, para ver si tiene comentarios hijos.
M, por cada uno de los hijos encontrados, para ver si tiene hijos....
Segunda forma:
- Se obtienen todos los comentarios con objetoComentado==id.
- En php, se crea el árbol completo, usando el campo "padre" (hay formas muy eficientes de hacerlo)
Cuantas queries hacen falta?: 1 , independientemente de la cantidad de comentarios.
Forma hibrida:
- Se obtienen todos los comentarios que no tienen padre.
- Se hace una lista de esos ids de comentario, y se obtienen todos los hijos para todos esos ids.En memoria, se asigna cada uno a su padre respectivo.
- Se hace una lista de estos últimos ids, y se obtienen de nuevo todos los hijos, que se vuelven a asignar.
- Se termina cuando la query devuelva 0 filas.
Número de queries hechas: tantas como profundidad tenga el árbol.
Problema de ambas: cómo paginas? En el primer caso, es extraordinariamente dificil. En el segundo, es posible hacerlo, pero siempre se obtienen todas las rows de la BD, para paginar.
Segundo problema: Cuánto cuesta responder a la pregunta: dame todas las respuestas al comentario X ? En el primer caso, consiste en hacer queries recursivas (cuyo rendimiento dependerá del número de respuestas). En el segundo, requiere obtener el árbol completo.
- Caso 2:
En la BD se almacena el
path completo de respuestas, y el id del objetoComentado.
Es decir, en la tabla de comentarios, en vez del campo "padre", se almacena el "path":
El path, para un comentario "raiz", (no una respuesta), es su id:
Si el id es "100", su path es : "100#"
Los comentarios respuesta, tienen como path , el del padre, más su "id":
Si el id 200 es respuesta al 100, el path es "100#200#"
Desventajas:
Requiere más almacenamiento en la tabla, y, dependiendo de la profundidad máxima del árbol, el path puede requerir ser de tipo TEXT (ineficiente).
Ventajas:
Es fácil ordenar y paginar: Ordenando por el campo "path" se obtienen los primeros comentarios, y sus respuestas, antes que comentarios posteriores.
(Nota: la paginación de estructuras en árbol siempre va a seguir teniendo sus complicaciones, porque es otra operación que es muy natural para el concepto de "filas", pero extraña al concepto de "arbol")
Obtener todos los hijos de un determinado comentario,o respuesta, es muy sencillo.
En caso de que fuera necesario, operaciones del tipo "mover nodo", "eliminar nodo y todos sus hijos", etc, siguen siendo muy sencillas.
El número de queries para gestionarlo sigue siendo muy bajo.
Lo importante, siempre, es mantener bajo el número de queries.Cuantas menos hagas, muuuucho mejor.