Nelle versioni Modern MongoDB il modo più efficiente è semplicemente annotare l'array utilizzando le proprietà del documento esistenti. La notazione diretta degli array è stata introdotta in MongoDB 3.2:
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
O anche utilizzando $addFields
per "aggiungere" semplicemente la nuova proprietà ai documenti:
db.collection.aggregate([
{ "$addFields": {
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Se stai utilizzando MongoDB 2.6 e versioni successive, puoi farlo con il framework di aggregazione ed evitare di ripetere i risultati nel programma client per creare una nuova raccolta.
La caratteristica principale qui che ti aiuta è il $out
operatore per inviare l'output a una nuova raccolta. Ma anche essere un po' intelligenti per creare l'array di cui hai bisogno.
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"type": { "$literal": ["lat","long"] }
}},
{ "$unwind": "$type" },
{ "$group": {
"_id": "$_id",
"lat": { "$first": "$lat" },
"long": { "$first": "$long" },
"coordinates": {
"$push": {
"$cond": [
{ "$eq": [ "$type", "lat" ] },
"$lat",
"$long"
]
}
}
}},
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": "$coordinates"
}
}},
{ "$out": "newcollection" }
])
Quindi questo fa uso di $literal
operatore per specificare un nuovo array all'inizio della pipeline. Questo operatore inserirà il contenuto nella proprietà del documento esattamente come viene fornito. Quindi non sono consentite sostituzioni di variabili, quindi "letterali".
Per creare l'array "coordinates", svolgiamo semplicemente quel primo array che essenzialmente crea due di ogni documento con un valore diverso in "type". Questo viene quindi utilizzato nel $group
fase per $push
il valore "$lat" o "$long" su quell'array.
Infine usa $project
di nuovo per finalizzare la struttura del documento e quindi $out
invia tutto l'output alla nuova raccolta.
Tieni presente che questo ha senso solo se la tua intenzione è quella di creare una nuova raccolta ed evitare di inviare traffico "over the wire". Questo non può essere utilizzato esclusivamente all'interno del framework di aggregazione per rimodellare il tuo documento con l'intento di eseguire quindi una query "geospaziale" nella stessa pipeline di aggregazione delle query "geospaziali" funzioneranno solo quando effettivamente indicizzate su una raccolta .
Quindi questo può aiutarti a creare una nuova raccolta come desideri, ma almeno funge da esempio (o due esempi in realtà) di come creare un array da valori diversi con il framework di aggregazione.