En las versiones modernas de MongoDB, la forma más eficiente es simplemente anotar la matriz utilizando las propiedades del documento existente. La notación directa de matrices se introdujo en MongoDB 3.2:
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
O incluso usando $addFields
para simplemente "añadir" la nueva propiedad a los documentos:
db.collection.aggregate([
{ "$addFields": {
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Si está utilizando MongoDB 2.6 y superior, puede hacerlo con el marco de agregación y evitar los resultados en bucle en su programa cliente para crear una nueva colección.
La característica principal aquí que lo ayuda es el $out
operador para enviar la salida a una nueva colección. Pero también ser un poco inteligente para crear la matriz que necesita.
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" }
])
Esto hace uso de $literal
operador para especificar una nueva matriz en la cabeza de la canalización. Este operador pondrá contenido en la propiedad del documento exactamente como se suministra. Por lo tanto, no se permiten sustituciones de variables, por lo tanto, "literal".
Para crear la matriz de "coordenadas", simplemente desenrollamos esa primera matriz que esencialmente crea dos de cada documento con un valor diferente en "tipo". Esto luego se usa en el $group
etapa para condicionalmente $push
ya sea el valor "$lat" o "$long" en esa matriz.
Finalmente use $project
nuevamente para finalizar la estructura del documento y luego $out
envía toda la salida a la nueva colección.
Tenga en cuenta que esto solo tiene sentido si su intención es crear una nueva colección y evitar enviar tráfico "por cable". Esto no podría usarse únicamente dentro del marco de agregación para remodelar su documento con la intención de luego hacer una consulta "geoespacial" en esa misma canalización de agregación, ya que las consultas "geoespaciales" solo funcionarán cuando realmente estén indexadas en una colección. .
Entonces, esto puede ayudarlo a crear una nueva colección como desee, pero al menos sirve como ejemplo (o dos ejemplos en realidad) de cómo crear una matriz a partir de diferentes valores con el marco de agregación.