È necessario eseguire un'operazione di aggregazione con due unwind tappe e un singolo palco. La regola base è che ti rilassi tante volte quanto il livello di profondità del nido. Qui il livello di nidificazione è 2, quindi ci rilassiamo due volte.
collection.aggregate([
{$unwind => "$Countries"},
{$unwind => "$Countries"},
{$group => {"_id":"$_id","Countries":{$push => "$Countries"}}}
])
La prima $unwind
fase produce il risultato:
{
"_id" : ObjectId("54a32e0fc2eaf05fc77a5ea4"),
"Countries" : [
"Spain",
"France"
]
}
{
"_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"),
"Countries" : [
"Spain"
]
}
{
"_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"),
"Countries" : [
"Russia",
"Egypt"
]
}
La seconda $unwind
fase appiattisce ulteriormente la Countries
matrice:
{ "_id" : ObjectId("54a32e0fc2eaf05fc77a5ea4"), "Countries" : "Spain" }
{ "_id" : ObjectId("54a32e0fc2eaf05fc77a5ea4"), "Countries" : "France" }
{ "_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"), "Countries" : "Spain" }
{ "_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"), "Countries" : "Russia" }
{ "_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"), "Countries" : "Egypt" }
Ora finali $group
gruppi stadio i record in base al _id
e accumula i nomi dei paesi in un singolo array.
{
"_id" : ObjectId("54a32e4ec2eaf05fc77a5ea5"),
"Countries" : [
"Spain",
"Russia",
"Egypt"
]
}
{
"_id" : ObjectId("54a32e0fc2eaf05fc77a5ea4"),
"Countries" : [
"Spain",
"France"
]
}
Se si desidera mantenere altri campi nel documento, allora è necessario specificare esplicitamente i nomi dei campi diversi dal campo del paese, (campo1, campo2, ecc ..), utilizzando l'operatore $first
. È possibile scrivere/sovrascrivere una raccolta specificando il nome della raccolta nella fase $out
.
collection.aggregate([
{$unwind => "$Countries"},
{$unwind => "$Countries"},
{$group => {"_id":"$_id","Countries":{$push => "$Countries"},
"field1":{$first => "$field1"}}},
{$out => "collection"}
])
è necessario specificare in modo esplicito i campi in modo che non si ottiene un ridondante Countries
campo.
È possibile utilizzare la variabile di sistema $$ROOT
per memorizzare l'intero documento, ma che renderebbero il redundant.One Countries
campo al di fuori del doc
e uno all'interno della doc
.
collection.aggregate([
{$unwind => "$Countries"},
{$unwind => "$Countries"},
{$group => {"_id":"$_id","Countries":{$push => "$Countries"},
"doc":{$first => "$$ROOT"}}},
{$out => "collection"}
])
ho scritto il risultato 3 secondi prima di quanto si;), era solo interessante. comunque +1 – Disposer
@Disposer Sì, mi hai battuto.Ci è voluto tempo per formattare i risultati :), +1 per la tua aggregazione. :) – BatScream
Grazie. Posso chiarire ancora due domande. Ho notato che questo operatore di gruppo restituisce solo i campi specificati (id e paesi). È possibile includere tutti gli altri campi senza specificare manualmente ciascuno di essi. Poiché ci sono molti altri campi, e il db non è ancora ottimizzato, ci sono anche campi unici condivisi solo da una porzione molto piccola di documenti e sarebbe dannatamente difficile cercare e specificarli tutti. E in secondo luogo, forse una domanda stupida: come sovrascrivo la raccolta originale con l'output aggregato? – Anton