2011-11-19 1 views
11

Diciamo che ho una collezione di documenti quali:Come imporre chiavi esterne nei database NoSql (MongoDB)?

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

E, d'altra parte i proprietari sono rappresentati come una raccolta differenziata:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

Come posso fare in modo che, quando Inserisco un documento che fa riferimento all'utente in modo corretto. Nella RDBMS vecchia scuola ciò potrebbe facilmente essere fatto usando una chiave esterna.

So che posso verificare la correttezza dell'inserimento dal mio codice aziendale, MA se un utente malintenzionato manomette la richiesta al server e inserisce "proprietario": 100 e Mongo non restituisce alcuna eccezione.

Mi piacerebbe sapere come questa situazione dovrebbe essere gestita in un'applicazione di parole reali.

Grazie in anticipo!

+1

Se un utente malintenzionato può manomettere la richiesta, cosa ti fa pensare che non potrebbero manomettere l'eccezione di risposta? – deed02392

risposta

12

MongoDB non dispone di chiavi esterne (come si è presumibilmente notato). Fondamentalmente la risposta è quindi: "Non lasciare che gli utenti manomettano le richieste, ma lascia che l'applicazione inserisca i dati che seguono le tue regole di integrità referenziale".

MongoDB è fantastico in molti modi ... ma se trovi che hai bisogno di chiavi esterne, probabilmente non è la soluzione corretta al tuo problema.

13

Per rispondere alla domanda specifica - mentre MongoDB incoraggia la gestione delle relazioni a chiave esterna sul lato client, forniscono anche l'idea di "Riferimenti di database" - Vedere this help page.

Detto questo, Non è consigliabile utilizzare un DBRef. O lascia che il codice cliente gestisca le associazioni o (meglio ancora) collega i documenti insieme fin dall'inizio. Si consiglia di considerare l'incorporamento dei "documenti" del proprietario all'interno dell'oggetto proprietario stesso. Assemblare i documenti in modo che corrispondano ai modelli di utilizzo e MongoDB brillerà.

+0

+1 per un suggerimento su come ristrutturare per evitare questo problema. – deed02392

0

Vorrei anche raccomandare che se il nome utente è univoco, usarlo come _id. Salvi su un indice. Nel documento che si sta memorizzando, impostare il valore di 'proprietario' nell'applicazione come valore di 'nome utente' quando il documento viene creato e non lasciare mai che un altro pezzo di codice lo aggiorni.

Se esistono dei requisiti per modificare il proprietario, fornire le API appropirate con le regole aziendali implementate.

Non ci sarà bisogno di chiavi esterne.

+1

Tranne, se lo fai, se un utente vuole cambiare il suo nome utente, devi cancellare il record esistente e poi inserirne uno nuovo con il nome utente modificato. –

0

Se qualcuno vuole davvero applicare le chiavi esterne nel progetto/WebApp. Quindi dovresti adottare un approccio MixSQL, ad esempio SQL + NoSQL

Preferirei che i dati di Bulky che non hanno molti riferimenti possano essere archiviati nel database NoSQL Store. Come: tipo di dati Hotels o Places.

Ma se ci sono alcune cose serie come i moduli OAuth Tabelle, TokenStore e UserDetails e UserRole (Tabella di mappatura) ecc .... allora puoi andare con SQL.

0

Come soluzione NoSQL, è possibile utilizzare MariaDB (NewSQL) È una combinazione di SQL e NoSQL e implementata dagli sviluppatori MySQL con prestazioni eccezionali.

0

Questa è una relazione uno a uno. È meglio incorporare un documento in un altro, invece di mantenere raccolte separate. Controllare here su come modellarli in mongodb e i loro vantaggi.

Sebbene non esplicitamente menzionato nei documenti, l'incorporamento offre lo stesso effetto dei vincoli di chiave esterna. Voglio solo chiarire questa idea. Quando si dispone di due collezioni del genere:

C1:

{ "_id" : 0 , "owner":0 "name":"Doc1"},{ "_id" : 1 , "owner":1, "name":"Doc1"}, etc 

C2:

{ "_id" : 0 , "username":"John"}, { "_id" : 1 , "username":"Sam"} 

E se si dovesse dichiarare vincolo di chiave esterna C2._id fare riferimento C1._id (supponendo MongoDB lo permette) , significherebbe che non è possibile inserire un documento in C2 dovenon esiste in C1. Confronta questo con un documento incorporato:

{ 
    "_id" : 0 , 
    "owner" : 0, 
    "name" : "Doc1", 
    "owner_details" : { 
     "username" : "John" 
    } 
} 

Ora il campo owner_details rappresenta i dati della collezione C2, ed i campi rimanenti rappresentano i dati da C1. Non è possibile aggiungere un campo owner_details a un documento inesistente. Stai essenzialmente ottenendo lo stesso effetto.