Progettazione del database per comportamento generico

2

Ho alcune tabelle generiche. Uno di questi consente a un utente di commentare qualcosa, mentre l'altro consente a un utente di aggiungere qualcosa ai preferiti.

Inizialmente, avevo pensato che per rendere possibile e commentare qualsiasi cosa, avrei potuto avere un'altra tabella chiamata qualcosa come CommentSet e FavoriteSet , che sarebbe stata usata da Comments e Favorites che sarebbero quindi essere utilizzato come chiave esterna su tutto ciò che doveva essere "commentabile" o "favorito".

CommentSet
 - id

Comment
 - id
 - body
 - setId

Post
 - commentSetId
 - ...

Questo sembrava funzionare bene, ma c'erano alcuni svantaggi con questo approccio:

  • Non c'era modo di capire quale articolo fosse un preferito o un commento
  • Aggiunta la complessità che richiede la creazione delle righe "set" quando necessario

Invece ho pensato di usare chiavi esterne direttamente sulle tabelle:

Comment
 - id
 - body
 - postId (for example)
 - userId (another example)

Con questo approccio non sembrano esserci problemi e:

  • Ora è possibile capire su quale elemento è inserito il commento / preferito (usando l'FK)
  • Nessuna complessità aggiunta, devi solo creare un commento / preferito e nient'altro.

Una cosa di cui ero preoccupato era la performance, anche se non so per certo che questo sarebbe male per le prestazioni. Quale approccio dovrei usare, o c'è un modo migliore?

    
posta Sebastian Olsen 05.07.2018 - 07:54
fonte

3 risposte

1

Ci sono diversi modi per risolvere questo problema, ad esempio:

Elaborazione della soluzione 1

Per ogni tipo di cosa commentabile (tabella i.e.) nel tuo database, avresti una colonna commentSet .

La prima volta che un utente invia un commento per un elemento specifico (cioè riga), crei un nuovo commentSetid e metti tutti i commenti successivi sullo stesso oggetto nella tabella dei commenti con lo stesso set. Ovviamente, memorizzerai per ogni timestamp e id utente.

Questo approccio è flessibile. L'unico vincolo è prevedere la colonna commentSet dove necessario. Quando si visualizzano gli oggetti, è molto veloce trovare i commenti correlati. È anche molto facile trovare tutti i contributi di un utente specifico.

Lo svantaggio principale sarà quello di ritrovare gli elementi commentati (quando si avvia la navigazione da un utente o un set di commenti. Qui dovresti cercare ogni potenziale tabella che abbia una colonna commentSet. Questo potrebbe rallentare notevolmente la ricerca .

C'è una via d'uscita: nel commentSet inserisci un identificatore di classe (ad esempio qualcosa che identifichi in modo univoco la tabella contenente l'elemento da commentare). Anche se questo sarebbe facile da usare in modo programmatico, non è così bello, perché questo è molto difficile da usare nelle query SQL.

Elaborazione della soluzione 2

Questo è un buon modo per indirizzare la navigazione bidirezionale tra elementi e commenti commentabili. Il motore relazionale dovrebbe gestirlo molto velocemente.

Il problema è che la tua tabella dei commenti dipende da tutte le altre tabelle commentabili. Ogni volta che crei una nuova classe / tabella commentabile, dovrai aggiornare anche la gestione dei commenti ... Non è nel senso di separazione delle preoccupazioni.

Inoltre, se hai molti oggetti diversi che possono essere commentati, avresti molte colonne vuote nella tabella dei commenti.

Ma va bene. Di fatto questa è un'implementazione del ereditarietà di tabelle singole modello di mappatura relazionale dell'oggetto.

altre soluzioni

Potresti anche considerare altri modelli orm come ereditarietà di tabelle concrete o mappatori di ereditarietà.

    
risposta data 05.07.2018 - 10:31
fonte
0

Manca un'altra possibile soluzione, che è simile alla seguente:

Comment
 - id
 - body
 - subject_id
 - subject_type

Il campo subject_id conterrà l'ID di o un utente, un post o qualsiasi altra cosa che possa essere commentata. E la colonna subject_type sarebbe un enum che indica se si tratta di un utente, di un post o di qualsiasi altra cosa. Questa è, per quanto ne so, la più normalizzata delle possibili soluzioni.

    
risposta data 06.07.2018 - 11:35
fonte
0

Questo suona come un paio di classiche relazioni uno-a-molti. Non hai indicato quale sia la cosa che stanno commentando e / o favorendo quindi chiamerò semplicemente "Post" qui. È l'entità radice del tuo Entity-Relationship-Model (ERM) ... noto anche come uno "schema" di database.

Considera questo schema ...

Post
- id  (PK)
- content

Comment
- id  (PK)
- post-id  (FK to Post.id)
- content

Favorite
- id  (PK)
- post-id  (FK to Post.id)
- type
    
risposta data 07.07.2018 - 22:40
fonte

Leggi altre domande sui tag