Nas versões modernas do MongoDB, a maneira mais eficiente é simplesmente anotar a matriz usando as propriedades do documento existente. A notação direta de arrays foi introduzida no MongoDB 3.2:
db.collection.aggregate([
{ "$project": {
"lat": 1,
"long": 1,
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Ou mesmo usando
$addFields
para simplesmente "anexar" a nova propriedade aos documentos:db.collection.aggregate([
{ "$addFields": {
"geometry": {
"type": { "$literal": "Point" },
"coordinates": [ "$lat", "$long" ]
}
}},
{ "$out": "newcollection" }
])
Se você estiver usando o MongoDB 2.6 e superior, poderá fazer isso com a estrutura de agregação e evitar repetir resultados em seu programa cliente para criar uma nova coleção.
O principal recurso aqui que ajuda você é o
$ fora
operador para enviar a saída para uma nova coleção. Mas também sendo um pouco inteligente para criar o array que você precisa. 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" }
])
Portanto, isso faz uso do
$literal
operador para especificar uma nova matriz na cabeça do pipeline. Este operador colocará o conteúdo na propriedade do documento exatamente como é fornecido. Portanto, nenhuma substituição de variável é permitida, portanto, "literal". Para criar o array "coordenados", simplesmente desenrolamos o primeiro array que essencialmente cria dois de cada documento com um valor diferente em "type". Isso é então usado no
$group
estágio para condicionalmente $push
o valor "$lat" ou "$long" nesse array. Por fim, use
$project
novamente para finalizar a estrutura do documento e, em seguida, $out
envia toda a saída para a nova coleção. Observe que isso só faz sentido se sua intenção for criar uma nova coleção e evitar o envio de tráfego "pelo cabo". Isso não pode ser usado puramente dentro da estrutura de agregação para remodelar seu documento com a intenção de fazer uma consulta "geoespacial" nesse mesmo pipeline de agregação, pois as consultas "geoespaciais" só funcionarão quando realmente indexadas em uma coleção .
Portanto, isso pode ajudá-lo a criar uma nova coleção como você deseja, mas pelo menos serve como exemplo (ou dois exemplos na verdade) de como criar uma matriz de valores diferentes com a estrutura de agregação.