Implementazione di commenti e Mi piace nel database

Sono uno sviluppatore di software. Mi piace codificare, ma odio i database … Attualmente sto creando un sito Web in cui un utente può contrassegnare un’entity framework come gradita (come in FB), taggarla e commentarla .

Rimango bloccato sulla progettazione di tabelle di database per la gestione di questa funzionalità. La soluzione è banale, se possiamo farlo solo per un tipo di cosa (ad esempio foto). Ma ho bisogno di abilitare questo per 5 cose diverse (per ora, ma presumo anche che questo numero possa crescere, man mano che l’intero servizio cresce).

Ho trovato alcune domande simili qui, ma nessuno di loro ha una risposta soddisfacente, quindi sto facendo di nuovo questa domanda.

La domanda è: come progettare correttamente, in modo efficiente ed elastico il database, in modo che possa memorizzare commenti per tabelle diverse, i Mi piace per tabelle e tag diversi per loro. Qualche modello di progettazione come risposta sarà la cosa migliore;)

Descrizione dettagliata : ho un User tabella con alcuni dati utente e altre 3 tabelle : Photo con fotografie , Articles con articoli , Places con luoghi . Voglio abilitare qualsiasi utente registrato a:

  • commentare uno di quei 3 tavoli

  • segnare uno di loro come è piaciuto

  • taggagli qualcuno con qualche tag

  • Voglio anche contare il numero di Mi piace per ogni elemento e il numero di volte in cui è stato utilizzato quel particolare tag.

1 ° approccio :

a) Per i tag , creerò un Tag [TagId, tagName, tagCounter] tabella Tag [TagId, tagName, tagCounter] , quindi creerò tabelle di relazioni many-to-many per: Photo_has_tags , Place_has_tag , Place_has_tag .

b) Lo stesso conteggio per i commenti.

c) LikedPhotos [idUser, idPhoto] un tavolo LikedPhotos [idUser, idPhoto] , LikedArticles[idUser, idArticle] , LikedPlace [idUser, idPlace] . Il numero di Mi piace sarà calcolato per query (che, presumo sia male). E…

Non mi piace molto questo disegno per l’ultima parte, mi ha un cattivo odore;)

2 ° approccio :

ElementType [idType, TypeName == some table name] una tabella ElementType [idType, TypeName == some table name] che verrà ElementType [idType, TypeName == some table name] dall’amministratore (me) con i nomi delle tabelle che possono essere apprezzate , commentate o taggate . Quindi creerò le tabelle :

a) LikedElement [idLike, idUser, idElementType, idLikedElement] e lo stesso per commenti e tag con le colonne appropriate per ciascuno. Ora, quando voglio fare una foto, inserirò:

 typeId = SELECT id FROM ElementType WHERE TypeName == 'Photo' INSERT (user id, typeId, photoId) 

e per i luoghi:

 typeId = SELECT id FROM ElementType WHERE TypeName == 'Place' INSERT (user id, typeId, placeId) 

e così via … Penso che il secondo approccio sia migliore, ma mi sento anche che manchi qualcosa anche in questo design …

Alla fine, mi chiedo anche quale sia il posto migliore dove riporre il contatore per quante volte l’elemento è piaciuto. Posso pensare solo in due modi:

  1. nella tabella elemento ( Photo/Article/Place )
  2. per select count ().

Spero che la mia spiegazione del problema sia più approfondita ora.

La soluzione più estensibile è avere una sola tabella “base” (collegata a “Mi piace”, tag e commenti) e “ereditare” tutte le altre tabelle da essa. L’aggiunta di un nuovo tipo di quadro comporta solo l’aggiunta di una nuova tabella “ereditata”, che quindi si inserisce automaticamente nell’intero macchinario tipo / tag / commento.

Il termine entity framework-relazione per questo è “categoria” (consultare la Guida ai metodi ERwin , sezione: “Relazioni sottotipo”). Il simbolo della categoria è:

Categoria

Supponendo che un utente possa apprezzare più entity framework, uno stesso tag può essere utilizzato per più di un’ quadro, ma un commento è specifico per l’ quadro, il tuo modello potrebbe assomigliare a questo:

Diagramma ER


A proposito, ci sono circa 3 modi per implementare la “categoria ER”:

  • Tutti i tipi in una tabella.
  • Tutti i tipi di calcestruzzo in tabelle separate.
  • Tutti i tipi concreti e astratti in tabelle separate.

A meno che tu non abbia requisiti di prestazioni molto stringenti, il terzo approccio è probabilmente il migliore (nel senso che le tabelle fisiche corrispondono a 1: 1 le entity framework nel diagramma sopra).

Dal momento che tu “odio” i database, perché stai cercando di implementarne uno? Invece, sollecita l’aiuto di qualcuno che ama e respira questa roba.

Altrimenti, impara ad amare il tuo database. Un database ben progettato semplifica la programmazione, l’ingegneria del sito e ne perfeziona il funzionamento continuo. Anche un progettista esperto di d / b non avrà previsioni complete e perfette: saranno necessari alcuni cambiamenti dello schema lungo il percorso man mano che emergeranno modelli di utilizzo o cambieranno i requisiti.

Se si tratta di un progetto one man, programmare l’interfaccia del database in semplici operazioni utilizzando stored procedure: add_user, update_user, add_comment, add_like, upload_photo, list_comments, ecc. Non incorporare lo schema in nemmeno una riga di codice. In questo modo, lo schema del database può essere modificato senza influenzare alcun codice: solo le stored procedure dovrebbero conoscere lo schema.

Potrebbe essere necessario rifattorizzare lo schema più volte. E ‘normale. Non preoccuparti di renderlo perfetto la prima volta. Basta renderlo abbastanza funzionale per prototipare un progetto iniziale. Se hai il lusso del tempo, usane un po ‘, quindi elimina lo schema e fallo di nuovo. È sempre meglio la seconda volta.

Questa è un’idea generale per favore non prestare molta attenzione allo stile dei nomi dei campi, ma più alla relazione e alla struttura

inserisci la descrizione dell'immagine qui

Questo pseudocodice riceverà tutti i commenti della foto con ID 5
SELEZIONA * DA azioni
DOVE actions.id_Stuff = 5
AND actions.typeStuff = “foto”
AND actions.typeAction = “commento”

Questo pseudocode otterrà tutti i Mi piace o gli utenti a cui è piaciuta la foto con ID 5
(puoi usare count () per ottenere solo la quantità di Mi piace)

 SELECT * FROM actions WHERE actions.id_Stuff = 5 AND actions.typeStuff="photo" AND actions.typeAction = "like" 

per quanto ho capito sono necessari diversi tavoli C’è una relazione molti a molti tra di loro.

  • Tabella che memorizza i dati dell’utente come nome, cognome, data di nascita con un campo identity framework.
  • Tabella che memorizza i tipi di dati. questi tipi possono essere foto, condivisioni, collegamenti. ogni tipo deve avere una tabella univoca. quindi, c’è una relazione tra le loro tabelle individuali e questa tabella.
  • ogni diverso tipo di dati ha la sua tabella. ad esempio, aggiornamenti di stato, foto, collegamenti.
  • l’ultima tabella è per molti a molti relazione memorizzando un id, id utente, tipo di dati e ID dati.

Guarda i modelli di accesso di cui avrai bisogno. Qualcuno di loro sembra aver reso particolarmente difficile o inefficiente la mia unica scelta di design o l’altra?

Se non preferisci quello che richiede meno tavoli

In questo caso:

  1. Aggiungi commento: scegli una particolare tabella molti / molti o inserisci in una tabella comune con un identificatore specifico noto per ciò che è piaciuto, penso che il codice cliente sarà leggermente più semplice nel secondo caso.
  2. Trova i commenti per l’articolo: qui sembra che l’utilizzo di una tabella comune sia leggermente più semplice: abbiamo solo una singola query parametrizzata per tipo di quadro
  3. Trova i commenti di una persona su un tipo di cosa: query semplice in entrambi i casi
  4. Trova tutti i commenti di una persona su tutte le cose: questo sembra poco nodoso in entrambi i casi.

Penso che il tuo approccio “discriminato”, l’opzione 2, presenti in alcuni casi domande più semplici e non sembri molto peggio negli altri, quindi ci andrei.

Sicuramente vai con il secondo approccio in cui hai una tabella e memorizza il tipo di elemento per ogni riga, ti darà molta più flessibilità. Fondamentalmente quando qualcosa può essere fatto logicamente con meno tabelle è quasi sempre meglio andare con meno tabelle. Un vantaggio che mi viene in mente in questo momento sul tuo caso particolare, considera di voler eliminare tutti gli elementi graditi di un determinato utente, con il tuo primo approccio devi pubblicare una query per ogni tipo di elemento ma con il secondo approccio che può essere fatto con una sola query o considerare quando si desidera aggiungere un nuovo tipo di elemento, con il primo approccio comporta la creazione di una nuova tabella per ogni nuovo tipo, ma con il secondo approccio non si dovrebbe fare nulla …

Prendi in considerazione l’utilizzo della tabella per quadro per i commenti e così via. Altre tabelle: migliore condivisione e ridimensionamento. Non è un problema controllare molte tabelle simili per tutti i framework che conosco.

Un giorno dovrai ottimizzare le letture da tale struttura. Puoi facilmente creare tabelle di agitazione su quelle di base e perdere un po ‘di scrittura.

Un grande tavolo con dizionario potrebbe diventare incontrollabile un giorno.