I moderna MongoDB-utgåvor är det mest effektiva sättet att helt enkelt notera arrayen med de befintliga dokumentegenskaperna. Direkt notation av arrayer introducerades i MongoDB 3.2:
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Eller till och med använda $addFields
för att helt enkelt "lägga till" den nya egenskapen till dokumenten:
db.collection.aggregate([
{ "$addFields": {
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Om du använder MongoDB 2.6 och senare kan du göra detta med aggregeringsramverket och undvika looping av resultat i ditt klientprogram för att skapa en ny samling.
Huvudfunktionen här som hjälper dig är $ ut
operatör för att skicka utdata till en ny samling. Men också att vara lite smart för att skapa den array som du behöver.
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" }
])
Så detta använder sig av $literal
operatör för att ange en ny array i spetsen av pipelinen. Denna operatör kommer att placera innehållet i dokumentegenskapen exakt hur den levereras. Så inga variabelsubstitutioner är tillåtna, därav "bokstavligen".
För att skapa "coordintes" arrayen, kopplar vi helt enkelt upp den första arrayen som i huvudsak skapar två av varje dokument med ett annat värde i "type". Detta används sedan i $group
steg för att villkorligt $push
antingen värdet "$lat" eller "$long" på den arrayen.
Använd slutligen $project
igen för att slutföra dokumentstrukturen och sedan $out
skickar all utdata till den nya samlingen.
Observera att detta bara är vettigt om din avsikt är att skapa en ny samling och undvika att skicka trafik "över tråden". Detta kunde inte användas enbart inom aggregeringsramverket för att omforma ditt dokument med avsikten att sedan göra en "geo-spatial" fråga i samma aggregeringspipeline eftersom "geo-spatiala" frågor bara fungerar när de faktiskt indexeras på en samling .
Så det här kan hjälpa dig att skapa en ny samling som du vill, men den fungerar åtminstone som exempel (eller två exempel faktiskt) på hur man skapar en array av olika värden med aggregeringsramverket.