Il modo più veloce per restituire un elenco di record in base a molte relazioni molti-a-molti

0

Sto sviluppando un'API in Rails e viene stabilito il seguente requisito (è molto più complicato, ma voglio fare un semplice esempio):

  1. Ci sono users e messages .
  2. users ha un sesso ( gender_id ), appartiene a un paese ( country_id ) e ha anche uno stato civile ( civil_status_id ).
  3. Quando viene creato un messaggio, questi possono essere indirizzati a diversi users a seconda dei suoi attributi (cioè più paesi, più stati civili e un genere), ma un messaggio può anche essere globale e questo significa che dovrebbe essere indirizzato a tutti gli utenti (questo è determinato con un attributo boolean chiamato global in ogni record di messaggio).
  4. Mi viene anche chiesto di consentire eccezioni se un messaggio è dichiarato globale, questo significa che admin nell'app dovrebbe essere in grado di creare un "globale", inclusi tutti i paesi ad eccezione di Russia e Cina e anche esclusi utenti vedovi.
  5. Ogni utente ha una casella di posta massima di 20 messaggi.

Qual è la mia soluzione per questo?

Per soddisfare questo requisito, ho pensato di fare quanto segue, ma ho molti dubbi, soprattutto mi interessa non avere un sacco di carico nell'applicazione ogni volta che l'utente vuole vedere i suoi messaggi, perché nella prima luogo ci sono centinaia di paesi, più stati civili e il numero di utenti può essere da decine a decine di migliaia o anche di più. Quindi qualsiasi critica o miglioramento è il benvenuto.

  1. Nell'app sono attualmente presenti i modelli User e Message , ma il problema con i messaggi è stato gestito male, ad esempio durante la creazione di un messaggio l'amministratore poteva scegliere solo un paese, uno stato civile, un genere (questo dovrebbe rimanere la stessa perché ci sono solo due generi nell'app, quindi scegliere maschi e femmine sarebbe una sinonimo di globale). In altre parole, la tabella degli utenti aveva un country_id , civil_status_id , gender_id e hai ricevuto un messaggio se questo messaggio era globale o c'era una corrispondenza tra il tuo% e il country_id , gender_id o civil_status .

Questo è stato creato con il seguente codice:

Message.all.where("global = ? OR civil_status_id = ? OR country_id = ?  OR gender_id = ?", true, user.civil_status_id, user.country_id, user.gender_id).limit(20)

Dove user era current_user .

  1. Per coprire i punti 3 e 4 (messaggi indirizzati a utenti di diversi paesi, stati civili, ecc. e messaggi globali con eccezioni) stavo pensando a quanto segue:

    2.1 Crea le tabelle di join civil_statuses_messages e countries_messages mentre gender_id rimane nella tabella users .

    2.2 Quindi, quando viene visualizzato un messaggio, le tabelle di join civil_statuses_messages e countries_messages devono essere compilate in base alla popolazione target dichiarata dall'amministratore.

    2.3 Infine, quando qualcuno vuole vedere la posta in arrivo, l'azione associata al ritorno dei messaggi che l'utente dovrebbe vedere dovrebbe creare una matrice e passare attraverso gli ultimi messaggi creati, uno per uno. Quindi se un messaggio è impostato su globale tutte le associazioni con paesi, genere o stato civile dovrebbero essere considerate come esclusioni, e quindi il messaggio dovrebbe essere scartato se l'utente è, ad esempio, da uno dei paesi in message.countries (dove messaggio è il messaggio corrente all'interno dell'iterazione).

    D'altra parte, se un messaggio non è impostato su globale, tutte le associazioni con paesi, sesso o stato civile dovrebbero essere considerate come inclusioni, e quindi il messaggio dovrebbe essere inserito nell'array se l'utente lo è, per esempio , da uno dei Paesi in message.countries (dove messaggio è il messaggio corrente all'interno dell'iterazione).

    Quando l'array raggiunge una dimensione di 20, deve essere restituito in JSON e il gioco è fatto.

I problemi che vedo

  1. Ad esempio, se nel sistema ci sono 20 mila messaggi, ma solo 5 messaggi sono indirizzati alle persone nel paese dello Yemen, quando una persona da quel paese vuole vedere la loro casella di posta, il sistema scorre attraverso 20 mila messaggi , in quanto non raggiungerebbe i 20 messaggi. Quindi questa soluzione è scarsa quando un messaggio è indirizzato a un pubblico molto piccolo.

Quali raccomandazioni proponi?

Non penso che questa applicazione abbia più di centinaia o migliaia di utenti o più di diverse dozzine o centinaia di messaggi (essendo realistici), ma non voglio essere limitato se molte persone scaricano e usano il app e ho inserito diversi admin.

    
posta OiciTrap 05.10.2018 - 18:10
fonte

1 risposta

1

Provalo e scopri .

Crea una tabella Messaggi e scrivi un breve programma per riempirlo con dati casuali. Poiché consideri 20.000 righe molto, inserisci 500.000 righe.

Esegui le tue domande e cronometrale. Se qualcuno ritorna più lentamente di quanto puoi lampeggiare, inserisci gli indici appropriati e riprova.

Trovare 5 record su 500.000 con un valore particolare è un gioco da ragazzi su un database moderno a condizione che l'indice sia stato impostato.

    
risposta data 05.10.2018 - 19:54
fonte

Leggi altre domande sui tag