2010-11-01 13 views
154

Sono sicuro che MongoDB non supporta ufficialmente "join". Cosa significa questo?MongoDB e "join"

Significa "Non possiamo collegare due raccolte (tabelle) insieme".?

Penso che se inseriamo il valore per _id nella raccolta A nello other_id nella raccolta B, possiamo semplicemente collegare due raccolte?

Se la mia comprensione è corretta, MongoDB può collegare due tabelle insieme, ad esempio, quando eseguiamo una query. Questo è fatto da "Riferimento", scritto in http://www.mongodb.org/display/DOCS/Schema+Design.

Quindi cosa significa "join"?

Mi piacerebbe conoscere la risposta perché è essenziale per imparare il design dello schema MongoDB. http://www.mongodb.org/display/DOCS/Schema+Design

+3

Infine aggiungono join a MongoDB 3.2 https://www.mongodb.com/blog/post/thoughts-on-new-feature-lookup – Soren

+4

Corretto, ** $ lookup ** è stato introdotto in MongoDB 3.2. I dettagli possono essere trovati su https://docs.mongodb.org/master/reference/reference/aggregation/lookup/#pipe._S_lookup – NDB

+0

Joins Esempio: http://www.fourthbottle.com/2016/07/joins-in -mongodb.html –

risposta

93

Non è un join dato che la relazione verrà valutata solo quando necessario. D'altra parte un join (in un database SQL) risolverà le relazioni e le restituirà come se fossero un'unica tabella ("unisci due tabelle in una sola").

Potete leggere di più su DBRef qui: http://docs.mongodb.org/manual/applications/database-references/

Ci sono due possibili soluzioni per risolvere i riferimenti. Uno è quello di farlo manualmente, come hai quasi descritto. Basta salvare _id di un documento in other_id di un altro documento, quindi scrivere la propria funzione per risolvere la relazione. L'altra soluzione consiste nell'utilizzare DBRefs come descritto nella pagina di manuale sopra, che renderà MongoDB in grado di risolvere la relazione lato client su richiesta. Quale soluzione scegli non importa tanto perché entrambi i metodi risolveranno la relazione lato client (si noti che un database SQL risolve i join sul lato server).

+14

Beh questa è una risposta corretta bt solleva la questione del motivo per cui MongoDB non supporta questo lato server? È solo per scoraggiare il suo uso e incoraggiare la denormalizzazione? Denormalizzare a volte è troppo inefficiente per le risorse. Perché forzare il turn-around del client/server quando questo è il caso? – GroovyDotCom

+15

@groovydotcom per capire questo devi capire la motivazione di entrambi i giorni e nosql. Nosql è ottimizzato per enormi quantità di letture e operazioni di scrittura. MASSICCIO. le macchine client e i server delle applicazioni sono più veloci di quanto fossero anni fa. La teoria è di scaricare le costose operazioni di join all'applicazione di un server e di macchine client per consentire ai server db di semplificare semplicemente le operazioni di lettura e scrittura semplici il più velocemente possibile. – Snowburnt

+1

Ciò significa, tuttavia, che lo scenario peggiore è che il cliente ha bisogno di entrambe le raccolte complete, che potrebbero essere enormi, giusto? Ad esempio se si dispone di una raccolta di tutti i profili utente e si desidera archiviare solo _id dell'utente contro il contenuto ...? – cstrat

6

Il primo esempio di collegamento mostra come i riferimenti MongoDB si comportano in modo simile al caricamento pigro non come un join. Non c'è una query che sta accadendo su entrambe le collezioni, piuttosto ne chiedi una e poi cerchi elementi da un'altra collezione come riferimento.

29

Il database non esegue join o il "collegamento" automatico tra i documenti. Comunque puoi farlo da solo lato cliente. Se hai bisogno di fare 2, va bene, ma se dovessi fare 2000, il numero di turnaround client/server renderebbe l'operazione lenta.

In MongoDB un modello comune è l'incorporamento. In relazione quando si normalizzano le cose si rompono in parti. Spesso in mongo questi pezzi finiscono per essere un documento unico, quindi non è necessario comunque un join. Ma quando ce n'è bisogno, lo si fa dal lato client.

Considerare il classico esempio ORDER, ORDER-LINEITEM. Un ordine e 8 elementi pubblicitari sono 9 righe relazionali; in MongoDB di solito modellizziamo questo come un singolo documento BSON che è un ordine con una serie di elementi pubblicitari incorporati. In tal caso, il problema di partecipazione non si pone. Tuttavia, l'ordine avrebbe un CLIENTE che probabilmente è una raccolta separata: il cliente potrebbe leggere il cust_id dal documento dell'ordine e quindi andare a prenderlo se necessario separatamente.

Ci sono alcuni video e diapositive per i colloqui di progettazione dello schema sul sito web mongodb.org.

+1

Ma prendi questo scenario, Supponiamo che l'ordine abbia 8 elementi pubblicitari, che gli elementi pubblicitari contengano il codice sku, Come recuperare gli ordini che hanno uno specifico sku. diciamo esempio "Voglio tutti gli ordini che hanno il codice sku: 'ABC001'". –

+4

@VijaySali lo cerchi ... db.collection.find ({"orders.lineitems.SKU": "ABC001"}); Riceverai indietro tutti gli ordini con tale SKU, assumendo che l'elemento pubblicitario incorporato abbia un campo SKU. Tutto dipende dallo schema – Snowburnt

2

Considerare l'utilizzo di mangusta? Ti dà la possibilità di fare join su dati mongo.

+2

Stai parlando di [popolare] (http://mongoosejs.com/docs/populate.html)? –

+0

? cosa, puoi spiegare ulteriormente? –

11

un tipo di partecipare a una query in MongoDB, è chiedere a un collezione per id che corrispondono, ha messo ids in un elenco (idlist), e fa trovare utilizzo su altro (o lo stesso) insieme con $ in: idlist

u = db.friends.find({"friends": something }).toArray() 
idlist= [] 
u.forEach(function(myDoc) { idlist.push(myDoc.id); }) 
db.family.find({"id": {$in : idlist} }) 
+0

è meglio che: 'u = db.friends.find ({ "amici": qualcosa}, {_ id: 0, id: 1}). ToArray()' ' db.family.find ({ "id" : {$ in: u}}) ' – user503601

1

Se si utilizza mangusta, si può semplicemente utilizzare (supponendo che si sta utilizzando documenti secondari e popolazione):

Profile.findById profileId 
    .select 'friends' 
    .exec (err, profile) -> 
    if err or not profile 
     handleError err, profile, res 
    else 
     Status.find { profile: { $in: profile.friends } }, (err, statuses) -> 
     if err 
      handleErr err, statuses, res 
     else 
      res.json createJSON statuses 

recupera Statuses che appartengono ad una delle Profile (profileId) amici. Amici è una serie di riferimenti ad altri Profiles. Profile schema con friends definito:

schema = new mongoose.Schema 
    # ... 

    friends: [ 
    type: mongoose.Schema.Types.ObjectId 
    ref: 'Profile' 
    unique: true 
    index: true 
    ] 
+2

Questa domanda non è stata contrassegnata in" CoffeeScript ". Se vuoi dare un esempio, IMHO, l'esempio dovrebbe essere in JavaScript. CoffeScript non è JavaScript. – scaryguy

+0

Non è stato anche taggato JavaScript. –

+0

JavaScript è il linguaggio di query shell ufficiale di MongoDB ... – scaryguy

4

Il fatto che MongoDB non è relazionale hanno portato some people to consider it useless. Penso che dovresti sapere cosa stai facendo prima di progettare un DB. Se si sceglie di utilizzare noSQL DB come MongoDB, è meglio implementare uno schema. Questo renderà le vostre collezioni - più o meno - simili a tabelle in database SQL. Inoltre, evitare la denormalizzazione (incorporamento), a meno che non sia necessario per motivi di efficienza.

Se si desidera progettare il proprio database noSQL, suggerisco di dare un'occhiata alla documentazione Firebase. Se capisci come organizzano i dati per il loro servizio, puoi facilmente progettare un modello simile per il tuo.

Come altri hanno sottolineato, si dovrà fare i join sul lato client, se non con Meteor (un framework JavaScript), si può fare il vostro unisce lato server con questo package (non so di altri quadro che ti consente di farlo). Tuttavia, ti suggerisco di leggere questo article prima di decidere di andare con questa scelta.

Edit 28.04.17: Recentemente Firebase pubblicato questo excellent series sulla progettazione di database NoSQL. Hanno anche evidenziato in one of the episodes i motivi per evitare join e come aggirare tali scenari denormalizzando il database.

0

Essendo un utente di MongoDB, dovevo recuperare i dati dalle raccolte correlate piuttosto frequentemente. Quando le persone memorizzano i dati dei database relazionali nei database NoSQL, diventa necessario unirsi a "join". Ecco una libreria che io, insieme con il mio amico, ho fatto eseguire Mongo si unisce in Python -

https://pypi.python.org/pypi/mongojoin/1.0.0

Il codice non è troppo complicato e ben la pena di provare!

44

A partire da Mongo 3.2 la risposta a questa domanda non è più corretta.Il nuovo operatore $ lookup aggiunto alla pipeline di aggregazione è essenzialmente identico ad un join esterno sinistro:

https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup

Dalla documentazione:

{ 
    $lookup: 
    { 
     from: <collection to join>, 
     localField: <field from the input documents>, 
     foreignField: <field from the documents of the "from" collection>, 
     as: <output array field> 
    } 
} 
+0

questo sarà bello – steampowered

+6

Limitazioni di $ lookup: 1) $ lookup supporta solo l'uguaglianza per la corrispondenza e l'uguaglianza deve essere compresa tra una singola chiave da ogni collezione. 2) La raccolta a destra per la ricerca $ non può essere ridotta –

0

mi sono imbattuto in molti post che cercano lo stesso - "Mongodb Join" e alternative o equivalenti. Quindi la mia risposta aiuterebbe molti altri che sono come me. Questa è la risposta che stavo cercando.

Sto usando Mongoose con framework Express. C'è una funzionalità chiamata Population al posto di join.

Come menzionato in Mongoose docs.

Non ci sono join in MongoDB ma a volte vogliamo ancora riferimenti a documenti in altre raccolte. Qui entra la popolazione.

Questo StackOverflow answer mostra un semplice esempio su come usarlo.