MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como criar um novo campo de matriz com a estrutura agregada


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.