Ciao Nicola,
la risposta corretta e' Ni.
Nell'esempio da te portato, tu puoi decidere se avere una collection Libri che embeddano i dati degli autori o la collection Autori i cui documenti embeddano i dati dei libri.
In un relazione questo caso sarebbe rappresentato che 3 tabelle non con due visto che e' una relazione molti a molti. Ma supponiamo, per semplicità, che ci sia un autore solo per ogni libro e che quindi la relazione sia 1 a molti.
Partiamo ad esempio facendo una sola collection Libri:
i documenti sarebbe fatti cosi':
{ _id:123,
titolo: "MongoDB in action",
descrizione:"bla bla bla",
ISBN: "12314",
autore: { Nome, cognome, data nascita, città, }
}
Ovviamente i dati degli autori vengono duplicati per ogni libro che hanno scritto, quindi se un autore trasloca devi fare l'update di tutti i documenti che contengono i suoi libri.
Se tu dovessi fare
db.libri.find({},{_id:0,autore:1})
Otterresti l'elenco degli autori ma con elementi duplicati. Per fare una "Distinct" devi usare la funzione aggregate.
Diciamo non molto comodo da gestire.
L'altra opzione e' di fare una collection autori, che sarebbe la tabella padre in una struttura relazionale.
In questo caso i documenti risulterebbero cosi':
{
"_id" : 123,
"nome" : "Massimo",
"cognome" : "Brignoli",
"citta" : "Milano",
"data_nascita" : ISODate("1969-07-11T00:00:00Z"),
"libri" : [
{
"ISBN" : "123",
"titolo" : "A",
"descrizione" : "AAA",
"edizione" : 1
},
{
"ISBN" : "434",
"titolo" : "B",
"descrizione" : "BBB",
"edizione" : 3
}
]
}
In questo caso per modificare i dati di un autore devi fare l'update di un singolo documento. Idem se cambiano i dati di un libro, siccome c'e' un solo autore per libro.
Per trovare l'autore di un libro:
db.autori.find({libri.ISBN: "123"})
per trovare tutti i libri il cui titolo contiene MongoDB
db.autori.find({libri.titolo: /MongoDB/})
Per trovare tutti i libri di un autore:
db.autori.find({nome:"xxx", cognome:"yyy"},{_id:0, libri:1})
I libri pero' ti vengono restituiti in un formato array, un po' brutto da manipolare.
Anche in questo caso ti viene in aiuto la funzione aggregate con gli operatori $match, $unwind e $project
db.autori.aggregate({$match: {nome:"Massimo"}},{ $unwind: "$libri"}, {$project:{ _id:0, libri:1 }}).pretty()
{
"libri" : {
"ISBN" : "123",
"titolo" : "A",
"descrizione" : "AAA",
"edizione" : 1
}
}
{
"libri" : {
"ISBN" : "434",
"titolo" : "B",
"descrizione" : "BBB",
"edizione" : 3
}
}
Elenco dei top autori di libri:
db.autori.aggregate({ $unwind: "$libri"}, {$group: {_id:{nome:"$nome", cognome:"$cognome"}, "libri": {$sum:1}}},{$project: {nome:"$_id.nome",cognome:"$_id.cognome",_id:0,libri:1}},{$sort: {libri:-1}},{$limit:10})
{ "libri" : 2, "nome" : "Massimo", "cognome" : "Brignoli" }
{ "libri" : 1, "nome" : "Nicola", "cognome" : "XXXXX" }
Come vedi con l'aggregate puoi manipolare e rigirare come vuoi il formato dell'output.
Massimo