Pregunta

Estoy construyendo un sitio web de EC para un cliente y el gerente del proyecto tuvo algunas ideas extrañas y estoy luchando por implementar lo que vendió al cliente.

Aquí viene mi problema principal y un resumen rápido de cómo está configurado el sistema: los productos están dentro de las categorías, las categorías podrían ser hijos de otra categoría. Por lo tanto, la categoría se presenta como un árbol en la barra lateral izquierda del sitio web.

El usuario puede examinar cualquier categoría, incluso las que no sean "hoja". categoría, si el usuario hace clic en una categoría no hoja, se debe presentar una lista como esa, por ejemplo, en una categoría de nivel 1 (lo mismo se aplica a las categorías de nivel 2): ??

big category 1
 category level ( 3 or 2 )
  product 1
  product 2
  product 3
 category level ( 3 or 2 ) 

Las cosas también deberían tener algo de paginación y estar presentes en 5 productos en cada página. Además, la categoría se debe ordenar de la misma manera en que aparecen en el menú del lado izquierdo ... mi esquema de base de datos es así:

+-------------+    +-------------+
+ category    +    + product     +
+-------------+    +-------------+
+ category_id +    + product_id  +
+ parent_id   +    + category_id + 
+-------------+    +-------------+

Realmente no puedo entender cómo debo codificar el SQL para asegurarme de que el producto aparezca en el orden en que deberían (como ordenar productos y categorías tiene menú).

También me preocupa el rendimiento de toda la configuración, si el usuario selecciona una '' hoja '' no categoría Tendría que buscar en toda la categoría secundaria y hacer una gran categoría IN (id1, id2, id3) y sé por experiencia que la declaración IN no funciona bien.

Si alguien ha encontrado el mismo diseño / problema y tiene algún consejo sobre cómo hacerlo, estaría agradecido.

¿Fue útil?

Solución

Puede usar el diseño Ruta materializada . Una ruta de directorio es un ejemplo de ruta materializada. Es decir, una serie de valores ancestrales, concatenados juntos, con algún carácter ('' / '' o '', '' son comunes) separándolos.

Entonces puede tener categorías:

+---------------------------------------------+
| cat_id | Name            | cat_path | depth |
+---------------------------------------------+
|    1   | Electronics     | 1/       |   1   |
|    2   | Digital cameras | 1/2/     |   2   |
|    3   | SLR cameras     | 1/2/3/   |   3   |
|    4   | Audio           | 1/4/     |   2   |
|    5   | Speakers        | 1/4/5/   |   3   |
|    6   | Wall Satellites | 1/4/5/6/ |   4   |
|    7   | Computers       | 1/7/     |   2   |
+---------------------------------------------+

Ahora, si desea todos los productos que están bajo Audio, puede hacer una consulta como:

SELECT p.*, pc.*
FROM Products p JOIN Categories pc ON (p.cat_id = pc.cat_id)
JOIN Categories c ON (pc.cat_path LIKE c.cat_path||'%')
WHERE c.name = 'Audio';

Por ejemplo, '1/4/5/6' LIKE '1/4 /%' es verdadero, por lo tanto, se incluyen los satélites de pared. Y lo mismo para cualquier otra subcategoría de audio.


Re su pregunta sobre el renderizado del menú: supongo que le gustaría que el menú renderice:  - Todos los antepasados ??de la categoría elegida.  - Todos los hermanos de los antepasados ??de la categoría elegida

Entonces, si elige 'Altavoces', verá:

  • Electrónica
    • Audio
      • Ponentes
    • Computadoras
    • Cámaras digitales

Pero no desea descendientes de computadoras o cámaras digitales (es decir, `` primos '' de altavoces).

SELECT uncle.name, uncle.depth
FROM Categories chosen
JOIN Categories ancestor ON (chosen.cat_path LIKE ancestor.cat_path||'%')
JOIN Categories uncle ON (ancestor.depth = uncle.depth
  AND SUBSTRING(REVERSE(ancestor.cat_path), 3, 100) = SUBSTRING(REVERSE(uncle.cat_path), 3, 100))
WHERE chosen.name = 'Speakers'
ORDER BY uncle.depth, uncle.name;

Estoy usando un truco para detectar tíos: compara las rutas, después de quitar el último elemento. Para hacer esto, invierta la cadena y luego quite el elemento primero . Esto debería funcionar al menos en MySQL y MS SQL Server, pero REVERSE () no es estándar y podría no ser portátil para otras marcas de RDBMS.

Tenga en cuenta que probablemente debería permitir más de un dígito para cada elemento en el cat_path , en cuyo caso el desplazamiento de la subcadena también debería aumentar.

Otros consejos

Desde una perspectiva de rendimiento, este es un mal diseño. Si un cliente hace clic accidentalmente en la categoría superior, ejecutará una consulta de todo su inventario. Esto probablemente tomará una cantidad de tiempo inaceptable. En términos web, esto se traduce en que el cliente pierde la paciencia, hace clic en el sitio de su rival y nunca vuelve a visitar su sitio .

Por supuesto, la optimización prematura es la raíz de todo mal y todo eso, pero es una buena idea evitar hacer cosas completamente tontas.

También estaría en desacuerdo con la idea de la navegación en árbol como un enfoque. Es demasiado pedirle a tus clientes que jueguen un juego de "Adivina cómo inventariamos nuestro stock". Además de cualquier otra cosa, en muchas esferas un producto puede pertenecer a más de una categoría, por lo que ajustarlos en una jerarquía es un proceso arbitrario. Como mínimo, probablemente debería tener un modelo de datos que permita asignar un producto a múltiples categorías de hojas. (Esto puede depender de la naturaleza de lo que está vendiendo y la granularidad de sus categorías).

Si su jefe insiste en su camino, aún tiene algunas opciones para mejorar el rendimiento de la consulta. Por ejemplo, podría tener una tabla que incluye todos los productos unidos por todas sus categorías principales ...

cat1 product1
cat1 product2
cat1 product3
cat1 product4
cat1 cat1.1 product1
cat1 cat1.1 product2
cat1 cat1.2 product3
cat1 cat1.2 product4
cat1 cat1.1 cat1.1.1 product1
cat1 cat1.1 cat1.1.2 product2
cat1 cat1.2 cat1.2.1 product3
cat1 cat1.2 cat1.2.2 product4

Tendría que mantener esto, a través de disparadores o como una vista materializada o mediante algún otro mecanismo (dependiendo de lo que ofrezca el sabor de su base de datos). Pero la sobrecarga de mantenerlo sería insignificante en comparación con los beneficios de rendimiento de no tener que volver a ensamblar la jerarquía del producto para cada consulta del cliente. Además, es poco probable que tenga tanta volatilidad en su inventario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top