Implementa un tag virtuale a livello di database

0

Ho un set di oggetti, per il quale gli utenti hanno applicato tag manualmente, qualunque cosa abbiano inventato. Mi piacerebbe implementare un motore di attività, in cui ogni attività potrebbe essere applicata agli oggetti da un tag. Per comodità, mi piacerebbe avere un tag virtuale aggiuntivo "Tutti gli oggetti" per applicare un'attività a tutti gli oggetti, indipendentemente dai tag.

Una singola attività potrebbe richiedere due (o più) serie di oggetti, ad es. "notificami le modifiche apportate a tutti i documenti dal tag X che sono stati pubblicati sul sito Web con tag Y".

Vedo tre modi per implementare questo requisito:

  1. Avere un'interfaccia utente e percorsi di codice business separati per il caso "Tutto". Questo potrebbe essere fattibile per casi semplici, ma nel mio caso porta ad avere quattro casi per l'esempio sopra, e potenzialmente anche peggio in altri casi.

  2. Avere un'interfaccia utente che consideri il caso "Tutti" come un normale tag (eccetto forse per rendere impossibile rimuovere elementi dal tag), e avere codice aziendale aggiungere automaticamente il tag ogni volta che elencho i tag in l'app o hanno casi speciali per il tag "Tutto" ogni volta che gestisco un tag.

  3. Avere un'interfaccia utente e un codice aziendale gestiscono il caso "Tutti" come un normale tag e implementare il tag "Tutti" virtuale a livello di database. Ciò significherebbe utilizzare le viste del database che aggiungerebbero il tag "Tutti" alla tabella dei tag e un'altra vista che aggiungerebbe il tag "Tutti" alla relazione m2m che elenca quali oggetti hanno quali tag.

La terza soluzione sembra la più sana per me, ma non ho molta esperienza con la programmazione a livello di database. Riesco a vedere i pro e i contro delle prime due soluzioni. Quali sono i problemi che potrei incontrare se avessi scelto di implementare la terza soluzione?

    
posta liori 15.01.2015 - 16:39
fonte

2 risposte

1

Mi sembra che tu stia mettendo il carrello un po 'prima del cavallo, specialmente da hai già un'implementazione parziale . Fai un passo indietro e chiediti cosa significa "tutto" e quale scopo serve.

In questo caso significa "senza condizioni o filtri", e lo scopo è quello di fornire un modo per l'utente di dire al sistema "Non mi interessa quali sono i tag". Il suo significato diventa rilevante nel momento in cui si esamina il valore reale dei tag, cosa che non accade finché non si arriva alla query del DB. Prima di questo, il valore del tag non ha importanza. Puoi semplicemente passarlo attraverso i tuoi oggetti di business normalmente.

all documents from tag X that were published on website tagged Y

Scrivo una query come questa (pseudo-SQL, sintassi corretta, ad es. ON, omessa per brevità):

FROM documents
INNER JOIN tags 
INNER JOIN publishedOn
INNER JOIN websites
WHERE tag = X AND website = Y

Se X è "tutto", lo farei in questo modo:

FROM documents
INNER JOIN publishedOn
INNER JOIN websites
WHERE website = Y

I tag non vengono interrogati perché non sono pertinenti. L'utente ha selezionato "tutti" che significa "Non mi interessa quale etichetta ha il documento". Qui, prendi una decisione sul livello di accesso ai dati e scegli la seconda query se la vedi. Se preferisci mantenere il tuo DAL più semplice e prendere la decisione all'interno della query SQL, è facile farlo:

FROM documents
INNER JOIN tags 
INNER JOIN publishedOn
INNER JOIN websites
WHERE (X = all OR tag = X) AND website = Y

Se usi una query come questa, potresti imbatterti nel problema del "numero magico", che significa "quale valore confronti X per vedere se significa tutto?" Una trappola comune sta usando un letterale hardcoded per il confronto. Ad esempio, @tagID = -1 . Questo non va bene. Quello che hai descritto facendo - aggiungendo "tutti" come "tag virtuale" - è un modo per prevenire questo problema, ma è molto più complicato del necessario.

Ancora una volta, chiediti quale sia il significato di "tutti" in relazione ai tuoi tag. È "Non mi interessa" o, più precisamente, "non specificato". C'è già un valore: null. Se l'utente seleziona "tutto", imposta la proprietà del filtro di tag sul tuo BO su null. Quando è il momento di ispezionare il filtro, se è nullo, non filtrare. La scelta tra l'esecuzione dell'ispezione nel DAL o DB è una questione su dove si vuole mettere un po 'di complessità in più (il che implica un minore aumento di manutenzione e un calo delle prestazioni che dovrebbe essere trascurabile).

In conclusione: non trattare "tutti" come tag perché non è uno . Cercare di fare il manganello renderà le cose difficili e confuse per chiunque mantenga il codice in futuro.

    
risposta data 16.02.2015 - 08:39
fonte
0

È possibile combinare potenzialmente 1 e 2, ma creare meno lavoro nel processo.

Inizialmente creerei la tua logica di query partendo dal presupposto che tutte le richieste sarebbero del tipo "mostra tutti i documenti pubblicati su tutti i siti web" e quindi estendilo per supportare il filtraggio per tag (aggiungere parametri alle query è più facile che portarle via ). Otterrai questo risultato semplicemente controllando se l'utente ha selezionato un tag per quell'oggetto e aggiungendo una clausola "where" (o qualsiasi equivalente per il DBMS scelto), se lo sono.

Da un punto di vista dell'interfaccia utente il tag "Tutto" sarebbe solo un indicatore visivo del fatto che non vengono applicati filtri di tag.

    
risposta data 15.01.2015 - 17:04
fonte

Leggi altre domande sui tag