Architettura database per “badge” Criteri di sistema e arbitrari (MySQL / PHP)

StackOverflow https://stackoverflow.com/questions/1049233

  •  20-08-2019
  •  | 
  •  

Domanda

Quickie-Domanda:

In sintesi, sono un po 'confuso su come avrei progettare un database che permette la creazione distintivo-regola a tempo indeterminato senza richiedere modifiche strutturali per l'utente-tabelle precedentemente esistente nel database.

Memorizzazione Badge Titolo, criteri, ecc Che cosa sarebbe che la tabella simile?

  • badge_id (1)
  • badge_title (10K Badge)
  • badge_image (10k.jpg)
  • badge_criteria ([post]> = 10000)
    ...

Winded-Domanda:

Vorrei realizzare un distintivo di sistema sui miei progetti personali, ma sto cercando un po 'di consigli su come si potrebbe meglio fare una cosa simile. Ho letto alcune delle domande qui circa distintivo-sistemi, ma non vedo il database di architettura ottenendo molta attenzione.

Badge che si basano su user-punti (ipotetico "10k Badge") sembrerebbe piuttosto semplice. Qualsiasi evento che interessa la reputazione degli utenti (upvotes, downvotes, risposta accettato, ecc) sarebbe richiamare un metodo di rivedere la nuova reputazione degli utenti, e potenzialmente assegnerà un badge.

Che i suoni di sistema piuttosto semplice, ma cosa che sembra come un database per l'amministratore che vuole creare innumerevoli quantità di badge con poco sforzo lungo la strada - alcune delle quali possono essere basata su criteri diversi, e non semplicemente la reputazione degli utenti.

User-reputazione è probabilmente un valore entro l'utente-record stesso. Ma idealmente, non si vuole per evitare di dover aggiungere nuovi campi alla tabella utente quando si creano nuovi distintivi? Per esempio il badge "Edited 100 voci" - non sarebbe creare una nuova colonna "entries_edited" all'interno degli Utenti Table, vero? E poi incrementare che dopo ogni voce-edited ...

Eventuali suggerimenti?

StackOverflow Archive:


Nota: Non sto chiedendo come associare badge con gli utenti. Non sto chiedendo come distintivi di aggiudicazione (che sarà fatto a livello di codice)

È stato utile?

Soluzione

Dato che i criteri di badge possono essere arbitrariamente complesso, non credo che è possibile memorizzare in una tabella di database suddiviso in elementi di dati "semplici". Cercando di scrivere un "regole motore" in grado di gestire i criteri arbitrariamente complesse sta andando a prendere giù il percorso di fondamentalmente riscrivere tutti gli strumenti che avete nel vostro linguaggio di programmazione.

Se si conosce in anticipo si desidera i cartellini limitati a solo alcuni campi (ossia distintivi sono basate solo off reputazione o il numero di modifiche o qualcosa del genere), allora è possibile memorizzare quelle di una semplice tabella come:

ReputationBadgeCriteria
  BadgeId
  BadgeName
  MinReputation

In alternativa, è possibile utilizzare un qualche tipo di DSL per scrivere le "regole", ma si finisce per dover creare anche un parser per analizzare le regole quando li si legge così come qualcosa di eseguire queste regole. A seconda della complessità che si desidera nella vostra DSL, questo non può essere un compito banale. Questo appare come il percorso che si sta andando nella tua domanda con avere una colonna Criteria (testo presumibilmente normale) che ha qualcosa come "[Reputazione]> 1000" o "[post]> 5" in esso. Si devono ancora analizzare ed eseguire tali norme e la complessità di scrivere qualcosa per farlo dipende da quanto sia complessa si desidera che tali regole siano.

Ti consiglierei di leggere questi quotidiana WTF articoli per informazioni sul motivo per cui questo approccio porta al dolore.

Altri suggerimenti

A seconda di quanto si vuole andare con esso, lo schema può diventare piuttosto complicato. Mi sembra che gli elementi di base necessari per monitorare sono:

Badges awarded
Points earned

Molto semplice finora, ma si vuole essere in grado di creare dinamicamente nuovi badge e nuovi punti categorie. premi Distintivo dipenderebbero a guadagnare punti in una o più categorie di punti che aggiungere fino a un certo importo. Quindi è necessario monitorare il rapporto tra le categorie di punti (e punti guadagnati) e distintivi:

Point categories
Badge categories

Quindi, la chiave sarebbe la vostra tabella di punti utente, che collegherebbe al punto categorie, che puntano a badge. Gli utenti guadagnano punti in una particolare categoria, che contribuirebbe a guadagnare punti nei confronti di uno o più distintivi.

badges:
badge_id
badge_name
required_points
....

point_categories:
point_id
category_name
weighting (optional)
...

point_groups:
badge_id
point_id
weighting (optional)
...

user_points:
user_id
point_id
points
...

user_badges:
user_id
badge_id
points_earned
badge_awarded (yes/no)
...

L'interfaccia "admin" permetterebbe a qualcuno di creare un nuovo badge e scegliere quali categorie punto sono necessari per guadagnare quel distintivo (point_groups). Ogni volta che un utente guadagna punti (user_points), si aggiorna la tabella user_points, quindi determinare quali badge quei punti avrebbero potuto contribuire a (point_groups). È quindi ricompilare i punti per i cartellini che sono stati colpiti dai punti guadagnati e aggiorna la tabella user_badges con l'point_earned. Poi controlla il campo points_earned in user_badges contro i required_points nella tabella distintivi.

È possibile ottenere molto più elaborato assegnando peso diverso alle diverse categorie di punti, o anche pesi diversi per categorie di punti per particolari distintivi. Ma questa configurazione permetterebbe una quantità illimitata di badge e categorie punto che deve essere creato e gestito abbastanza facilmente senza cambiare le strutture tabelle.

Se questo non è quello che state cercando è completamente, quindi penso che dovrei ottenere almeno un voto o due per un sacco di battitura.

Si potrebbe monitorare i tuoi utenti unici in una tabella e distintivi unici in un altro quindi creare una tabella di riferimento incrociato di relazionarsi con loro.

Un utente può avere molti scudetti e un badge può avere molti utenti.

create table users (
id int,
name varchar
)

create table badges (
id int,
badge_name varchar
)


create table user_badges_xref (
user_id int,
badge_id int
)

Le statistiche che potrebbero influenzare se un utente guadagna un badge sono tracciati come una parte della gestione del sito. quindi qualcosa di simile a una risposta di essere accettati sarebbe in uno schema che mette in relazione le domande e risposte. al fine di visualizzare la risposta e il proprietario della risposta, ci sarebbe una relazione con la tabella utente e trigger che avrebbe verificare la presenza di condizioni di badge ogni volta che è stato fatto un cambiamento.

  

Non sto chiedendo come badge premio.   Mi sto chiedendo come memorizzare i criteri all'interno del database.

Così si desidera memorizzare l'operazione logica necessaria per determinare se un badge è guadagnato in un campo da qualche parte?

Credo che d'accordo con l'altro manifesto che i criteri dovrebbero essere una parte della logica di business. Che la logica può essere sul lato applicazione o all'interno di un trigger. Penso che sia una questione di stile.

Se si dovesse davvero sposato l'idea di memorizzare i criteri in un campo, mi piacerebbe conservare lo SQL come parametri ed eseguirlo in modo dinamico.

Quindi, questo genere di cose sarebbe nel vostro campo criteri:

select "Badge Earned"
from all_posts 
where user_id = @user_id
having count(*) > 10000

Non vorrei creare un incremento per la modifica distintivo. Penso che si dovrebbe avere un posto di lavoro in esecuzione in background e contare () il numbero di messaggio modificato per i membri che non hanno il distintivo di editing ancora. Quando si vede che il conteggio è nel range che si desidera, si aggiunge una voce nel database che dire che l'utente ha il badge.

Credo che sia circa lo stesso per gli altri distintivi. Cercare di limitare il numero di scrittura e non scrivere direttamente il conteggio delle informazioni distintivo nella tabella utente. Utilizzare una tabella che conterrà informazioni distintivo e collegarlo alla tabella utente.

Mi scuso per essere brevi.

Per implementare un sistema come questo, potrei creare una tabella che memorizza sia i nomi di stored procedure o query effettivi che sarebbero stati utilizzati per determinare se un particolare utente ha guadagnato un badge.

badge_criteria
badge_key int
badge_criteria varchar(max)

È possibile estrarre ed eseguire le query per i badge che l'utente non ha guadagnato dal livello intermedio, ma non avrebbe dovuto apportare modifiche al codice o strutturali per aggiungere nuovi badge per il futuro.

sto avvicinando in questo modo: Creare una tabella per memorizzare tutti i cartellini, e hanno una colonna riferimento a una funzione che viene eseguita per vedere se il badge viene conferito. In questo modo la tabella rimane semplice e la logica per determinare i cartellini possono essere tenuti in codice, dove è più adatto.

Con questo metodo, i requisiti distintivo potrebbe anche essere collegati tra loro, in modo da formare le dipendenze più complesse. Ad esempio, l'utente deve ricevere tre separati, distintivi specifici w / in un certo periodo di tempo al fine di ottenere questo distintivo.

Questo sta per essere quasi impossibile da fare in database - badge aggiudicazione dovrebbe essere fatto nella vostra logica di business all'interno dell'applicazione. In questo modo, avete tutti i dati esistenti è necessario (modifiche, le visite, la reputazione, etc.) e può essere trattata come si vede in forma.

Aggiornamento:

Se in base a criteri intendi regole che determinano se e come viene assegnato il distintivo, poi che non è qualcosa che dovrebbe essere memorizzati nel database. Questo sarebbe quasi impossibile per testare e mantenere.

Se vuoi dire, per esempio, per memorizzare il "numero di modifiche", non c'è modo di ottenere intorno modifica di una tabella o una stored procedure per includere i dati che se ne avete bisogno.

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