I moderne MongoDB-udgivelser er den mest effektive måde blot at notere arrayet ved hjælp af de eksisterende dokumentegenskaber. Direkte notation af arrays blev introduceret i MongoDB 3.2:
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Eller endda ved at bruge $addFields
for blot at "føje" den nye egenskab til dokumenterne:
db.collection.aggregate([
{ "$addFields": {
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Hvis du bruger MongoDB 2.6 og nyere, kan du gøre dette med aggregeringsrammerne og undgå at sløjfe resultater i dit klientprogram for at oprette en ny samling.
Den vigtigste funktion her, der hjælper dig, er $ ud
operatør for at sende output til en ny samling. Men også at være lidt klog for at skabe det array, du har brug for.
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å dette gør brug af $literal
operatør for at specificere et nyt array i spidsen af pipelinen. Denne operatør vil placere indhold i dokumentegenskaben præcis hvordan det leveres. Så ingen variable substitutioner er tilladt, derfor "bogstaveligt".
For at skabe "coordintes"-arrayet afvikler vi simpelthen det første array, som i det væsentlige skaber to af hvert dokument med en anden værdi i "type". Dette bruges derefter i $group
trin til betinget $push
enten "$lat" eller "$long" værdien på det array.
Brug endelig $project
igen for at færdiggøre dokumentstrukturen og derefter $out
sender alt output til den nye samling.
Bemærk, at dette kun giver mening, hvis din hensigt er at oprette en ny samling og undgå at sende trafik "over the wire". Dette kunne ikke bruges udelukkende inden for aggregeringsrammen til at omforme dit dokument med den hensigt at lave en "geo-spatial" forespørgsel i den samme aggregeringspipeline, da "geo-spatial" forespørgsler kun vil fungere, når de faktisk er indekseret på en samling .
Så dette kan hjælpe dig med at oprette en ny samling, som du vil, men det fungerer i det mindste som eksempel (eller faktisk to eksempler) på, hvordan man opretter et array ud fra forskellige værdier med aggregeringsrammen.