Domanda

Sto costruendo un sito web CE per un cliente e il project manager ha avuto alcune idee strane e sto lottando per implementare effettivamente ciò che ha venduto al cliente.

Ecco il mio problema principale e un breve riepilogo di come il sistema è configurato: il prodotto è all'interno di categorie, le categorie potrebbero essere figli di un'altra categoria. Quindi la categoria è presentata come un albero nella barra laterale sinistra del sito Web.

L'utente può navigare in qualsiasi categoria, anche non " leaf " categoria, se l'utente fa clic su una categoria non foglia, una lista del genere deve essere presentata ad esempio su una categoria di livello 1 (lo stesso vale per le categorie di livello 2):

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

Le cose dovrebbero anche avere un po 'di paging e presenti su 5 prodotti in ogni pagina. Inoltre la categoria dovrebbe essere ordinata nello stesso modo in cui appaiono nel menu sul lato sinistro ... il mio schema DB è così:

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

Non riesco davvero a capire come dovrei codificare l'SQL per assicurarmi che il prodotto appaia nell'ordine in cui dovrebbero (come ordinare un prodotto e le categorie hanno un menu).

Inoltre, sono preoccupato per le prestazioni dell'intero setup, se l'utente seleziona un foglio non "a foglia". categoria Dovrei cercare in tutta la categoria figlio e creare una grande categoria IN (id1, id2, id3) e so per esperienza una lunga dichiarazione IN non funziona bene.

Se qualcuno ha riscontrato lo stesso design / problema e qualche consiglio su come farlo, sarei grato.

È stato utile?

Soluzione

Puoi utilizzare il design Percorso materializzato . Un percorso di directory è un esempio di percorso materializzato. Cioè, una serie di valori di antenati, concatenati insieme, con alcuni caratteri ("quot / /" o "," sono comuni) che li separano.

Quindi potresti avere categorie:

+---------------------------------------------+
| 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   |
+---------------------------------------------+

Ora se vuoi tutti i prodotti che si trovano in Audio, puoi fare una query come:

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';

Ad esempio, '1/4/5/6' LIKE '1/4 /%' è vero, quindi sono inclusi i satelliti da parete. E lo stesso per qualsiasi altra sottocategoria di audio.


Riguarda la tua domanda sul rendering del menu: suppongo che tu voglia renderizzare il menu:  - Tutti gli antenati della categoria scelta  - Tutti i fratelli degli antenati della categoria scelta

Quindi, se scegli "Altoparlanti", vedresti:

  • Elettronica
    • Audio
      • Altoparlanti
    • Computer
    • Fotocamere digitali

Ma non vuoi discendenti di computer o fotocamere digitali (ad es. "cugini" di altoparlanti).

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;

Sto usando un trucco per rilevare gli zii: confronta i percorsi, dopo aver rimosso l'ultimo elemento. Per fare ciò, invertire la stringa e quindi rimuovere l'elemento first . Questo dovrebbe funzionare almeno in MySQL e MS SQL Server, ma REVERSE () non è standard e potrebbe non essere portabile con altre marche di RDBMS.

Nota che probabilmente dovresti consentire più di una cifra per ogni elemento nel cat_path , nel qual caso dovrebbe aumentare anche l'offset della sottostringa.

Altri suggerimenti

Dal punto di vista delle prestazioni questo è un cattivo design. Se un cliente fa clic per errore sulla categoria più in alto, esegui una query dell'intero inventario. Ciò richiederà probabilmente un periodo di tempo inaccettabile. In termini Web ciò si traduce nel perdere la pazienza del cliente, facendo clic sul sito del tuo rivale e non visitando mai più il tuo sito .

Naturalmente, l'ottimizzazione prematura è la radice di tutto il male e di tutto ciò, ma è una buona idea evitare di fare cose completamente stupide.

Vorrei anche mettere in discussione l'idea della navigazione ad albero come approccio. Fa un po 'troppo male chiedere ai tuoi clienti di giocare a "Indovina come inventiamo le nostre azioni". A parte tutto, in molti settori un prodotto può appartenere a più di una categoria, quindi inserirli in una gerarchia è un processo arbitrario. Almeno probabilmente dovresti avere un modello di dati che supporti l'assegnazione di un prodotto a più categorie di foglie. (Questo può dipendere dalla natura di ciò che vendi e dalla granularità delle tue categorie).

Se il tuo capo insiste per la sua strada, hai ancora alcune opzioni per migliorare le prestazioni della query. Ad esempio, potresti avere una tabella che include tutti i prodotti uniti da tutte le categorie principali ...

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

Dovresti mantenerlo, tramite trigger o come vista materializzata o tramite qualche altro meccanismo (a seconda di ciò che offre il tuo sapore di database). Ma il sovraccarico di mantenerlo sarebbe insoddisfacente rispetto ai vantaggi in termini di prestazioni di non dover riassemblare la gerarchia del prodotto per ogni richiesta del cliente. Inoltre è improbabile che tu abbia tanta volatilità nel tuo inventario.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top