2011-11-30 17 views
9

Provengo da uno sfondo MySQL e sto cercando di avvolgere la mia testa attorno allo MongoDB. In particolare, sto cercando di concettualizzare come dovrei modellare le relazioni n:n con "Mongo way".Come modellare le relazioni molti-a-molti in MongoDB (per un utente MySQL)

Per questo esempio, supponiamo di avere due collections: users e interests. Dobbiamo essere in grado di rappresentare o eseguire una query per molte cose in nostri dati:

  • interessi dell'utente
  • Valutazione dell'utente di interesse, ad esempio, "Mi piace" o "antipatia"
  • utenti con un determinato interesse
  • contatore (che può essere incrementato/decrementato) di ogni valutazione dell'interesse
  • nome Interessi

In MySQL, avrei creato una tabella users_interests indicizzata su entrambi gli ID utente e ID interesse. Per il contatore, avrei avuto colonne separate per ciascun tipo di rating e ogni volta che un utente ha valutato/non valutato un interesse, ha eseguito una transazione per garantire che i conteggi non fossero mai falsi.

Ho provato reading about some schema designs, ma senza successo.

Puoi aiutare un'anima perduta a trovare la via?

risposta

10

Ottima domanda. Lasciatemi prima delineare un po 'di come funziona la relazione N: N, quindi andrò nei dettagli su ciascuno dei tuoi punti elenco.

N: N in MySQL normalmente si ha la tabella pivot che si associa tra utente e interessi (tabella user_interests). In mongo lo fai in modo un po 'diverso. Hai ancora una raccolta di utenti e interessi, tuttavia ora, invece, memorizzi un elenco di chiavi con interessi per un utente. SO qualcosa di simile:

User Collection { 
     "name":"Josh", 
     "user":"jsmith", 
     "interests":[ 
      { 
      "_id":12345, 
      "rating":"like" 
      }, 
      {..}.. 
     ] 
} 

Memorizzando i tuoi interessi in una lista che viene digitato fuori sul vostro tavolo di interesse, è possibile eseguire ciascuna delle azioni richieste. Se si desidera eseguire una query in base all'ID che si trova nella tabella degli interessi, eseguire una query utilizzando $in modifier.

Ora per i vostri interessi raccolta farei quanto segue:

User Interest { 
     "_id":objectId 
     "label":"Swimming", 
     "count":intValue 
} 

Quando si aggiunge un interesse a un documento utenti, la variabile di conteggio sarebbe poi dipenderà dalla definizione di tue valutazioni. Se stai memorizzando le tue valutazioni in un'area separata (o in logica), allora il valore che hai assegnato a loro sarebbe quello che ti riguarda quindi al valore int in interesse. IE: l'utente valuta meh (che ha un valore di 1), quindi aggiungere 1 al valore di conteggio.

Speriamo che questo sia utile e che abbia per lo meno portato ad altre idee su come strutturarlo!

Buona fortuna, ricorda MONGO È FANTASTICO.

+0

perché memorizzare l'ID? È improbabile che tu rinomini un interesse, ma mantieni i riferimenti, giusto? Inoltre, dovrai eseguire un '$ in' per visualizzare i nomi dei Mi piace. – mnemosyn

+0

@mnemosyn Di solito il percorso del codice prevede uno dei due scenari: 1: hai interesse a vedere quali utenti hanno o 2: vuoi vedere quali interessi ha un utente. Con il primo, hai già il nome e ora stai solo facendo una query su un ID (query più veloce) piuttosto che una stringa. Con il secondo, hai una lista di id che di nuovo stai interrogando sull'ID oggetto. Inoltre, se cambi un nome di interesse non devi refactoring attraverso ogni voce utente per aggiornarlo, in quanto tutto ciò che serve è l'ID di riferimento per quel particolare interesse nella raccolta di interessi. Spero che questo ti aiuti! – Petrogad

+0

@mnemosyn Cosa succede se decido di mettere in maiuscolo l'interesse, da "pesca" a "Pesca" o qualcosa del genere? – ceejayoz

1

Per mantenere un conteggio globale delle valutazioni di ciascun interesse, è necessario un insieme separato e indipendente in cui si aggiorna (sommare o sottrarre) le classificazioni utilizzando gli operatori di aggiornamento atomici quando e come/non mi piacciono le azioni per gli interessi vengono eseguite dagli utenti .

È possibile memorizzare l'interesse di ciascun utente sotto forma di una serie di sotto-documenti all'interno della Raccolta utente stessa.

La struttura JSON di questi dati sarebbe qualcosa di simile a:

db.User 
{ 
    name: 'joe', 
    ...., 
    interests : [{ name: 'swimming', rating: 10}, 
       { name: 'cooking', rating: 22 } 
       ] 
} 

Ora si può interrogare sui tasti interni utilizzando:

> db.User.find({ "interests.name" : "cooking" }) 

Ciò restituirà gli utenti che hanno un particolare interesse.

+0

In questo modo, il punteggio viene denormalizzato per ogni utente, ovvero ogni utente ha una copia del rating globale ('voto: 101) Questo non può essere mantenuto. – mnemosyn

+0

Qui c'è una differenza tra valutazioni e conteggi. Il conteggio è globale, la valutazione è relativa all'utente. La valutazione dovrebbe essere una stringa, tuttavia, e non un intero. –

+0

ok, ho frainteso la domanda sui PO. – mnemosyn