Aiutami a progettare questo caso d'uso

2

Ho le seguenti entità:

Dati:

  1. user_id
  2. Categorie: Interessi, Disinteressi, Categorie A, B C ...
  3. Ogni categoria ha sottocategorie: Interessi = Gioco, Fisica, Programmazione ecc.
  4. Ora ogni utente potrebbe appartenere a più sottocategorie.
  5. Quindi esiste una relazione M: N tra categorie e utenti.

Scala:

  1. 1 miliardo di utenti
  2. 100 categorie possono avere sottocategorie che vanno da 100 a 10.000

Operazioni necessarie

  1. Lettura e scrittura batch: selezione e proiezione date user_id. Per esempio. Ottieni tutti gli interessi dell'utente A

  2. Lettura e scrittura in tempo reale: ho bisogno di richiamare tutti gli utenti per un determinato campo come Interesse: Giochi.

Design corrente

Ho usato file separati per ogni sottocategoria contenente un elenco di utenti. Il server Redis ha coppie di valori-chiave come

<userId_InterestId:games,programming>

Tuttavia questo design ha molte limitazioni, come i tempi di accesso lenti dovuti alle operazioni del disco per ottenere tutti gli utenti per una determinata categoria. Numero enorme di chiavi in Redis, ovvero numero di ( utenti * numero di sottocategorie ).

Ho bisogno di un cambio di design

Il piano attuale è quello di utilizzare MongoDb per mantenere i dati gerarchici per l'utente < - > mappatura delle categorie.

<User_id, Interests, A, B, C>.

Ogni categoria avrà campi figli. Dal momento che MongoDB è in memoria, l'accesso ai DB utilizzando user_id dovrebbe essere più veloce, giusto? Ma che ne dici di una query inversa dove specifichi Interessi :: Programmazione come chiave? C'è un modo migliore per progettarlo?

    
posta Mangat Rai Modi 23.07.2015 - 12:34
fonte

3 risposte

1

Ecco cosa farei: non fare distinzioni tra categorie e sottocategorie. A ciascuna categoria sarebbe associata una categoria principale, che potrebbe essere nullo (categoria e non sottocategoria).

Se ho capito bene, le categorie non sono figli di utenti, quindi se un utente viene eliminato, non eliminerà le sue categorie. In tal caso, avrai bisogno di una tabella figlio di utenti chiamata UserCategories che associ un ID utente a una particolare categoria.

Quindi ora, se vuoi trovare tutte le categorie di un utente, hai una tabella figlia che ti dà queste informazioni. Inversamente se si dispone di una categoria, è possibile trovare tutti gli utenti associati al proprio ID in base a UserCategories. Eliminando la necessità per le sottocategorie di passare attraverso una categoria, hai collegato direttamente gli utenti con le sottocategorie e quindi diventa molto più facile da gestire.

Ovviamente nel tuo programma, puoi trattare una categoria con un genitore come una "sottocategoria" e trattarla in modo diverso, ma nel database significa solo una categoria con una categoria genitore.

    
risposta data 23.07.2015 - 13:31
fonte
0

Ci sono essenzialmente 3 aspetti di base del modello:

  1. Un elenco di utenti (identificati e indicizzabili che utilizzano user-id)
  2. Una struttura ad albero per le categorie e le sottocategorie
  3. La relazione M x N tra utenti e categorie / sottocategorie.

Se esistessero strutture più semplici di categorie come elenco lineare, difficilmente ci sarebbe una questione su come farlo. Tutto ciò di cui avevi bisogno era avere una mappa di id-utente: cat-id.

Ora, dato che l'elenco delle categorie è un albero e non una mappa lineare, non è poi così male! quello che dovresti fare idealmente è creare una mappa hash che può linearizzare la rappresentazione completamente gerarchica per ogni nodo foglia

per un semplice esempio -

  • HASH_VAL1: = GAMING
  • HASH_VAL2: = PROGRAMMAZIONE
  • HASH_VAL3: = PROGRAMMAZIONE- > C ++

Ora è facile vedere che la relazione MxN può essere impostata come user_id - elenco HASH_VALX.

Ci sono molti semplici vantaggi in questo sistema:

  1. La ricerca da Interesse a Utente è veloce come il contrario. L'inversione della mappa non richiede alcuna indicizzazione speciale.

  2. Puoi modificare e manipolare le categorie di interessi o disporre di altre informazioni che evolvono senza dover modificare la relazione user-interest_hash_value.

  3. Puoi convertire la foglia in nodo e tutto funziona ancora. Per esempio, un altro HASH_VALUE_X può iniziare a rappresentare PROGRAMMING- > C ++ - > Borland-C ++ che non influisce sulla relazione esistente che si trova al livello USER: PROGRAMMING- > C ++.

  4. Ad esempio, puoi aggiungere una relazione indiretta nave, se USER_X: HASH_VALUE_3 = PROGRAMMING- > C ++ implica USER_X: HASH-PROGRAMMING puoi mantenerlo semplicemente avendo un altro USER_X: HASH_VALUE_2 senza influenzare altre relazioni dati.

  5. Ultimo ma non meno importante, l'aggiunta di dati - i record di filtraggio possono essere piuttosto lineari e quindi possono essere ottimizzati in diversi modi (Caching, indicizzazione, ecc.) a seconda di come funziona il sistema.

risposta data 30.07.2015 - 15:35
fonte
-1

MongoDB ti consentirebbe di creare un indice su Interests . Quando si crea un indice per un campo che include matrici, ciascuna voce dell'array ottiene una voce di indice separata. Quindi quando i tuoi documenti hanno questo aspetto:

{
    _id:<<Objectid>>
    interests: [
        "Programming",
        "Knitting",
        "Paragliding"
    ]
}

una query come db.collection.find({interests:"Programming"}) ti darebbe tutti i documenti in cui l'array di interessi ha una voce "Programming" e trarrebbe vantaggio da un indice su interests .

    
risposta data 23.07.2015 - 13:50
fonte

Leggi altre domande sui tag