MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comment créer un nouveau champ tableau avec le framework agrégé

Dans les versions modernes de MongoDB, le moyen le plus efficace consiste simplement à noter le tableau à l'aide des propriétés de document existantes. La notation directe des tableaux a été introduite dans MongoDB 3.2 :

db.collection.aggregate([
  { "$project": {
    "lat": 1,
    "long": 1,
    "geometry": {
      "type": { "$literal": "Point" },
      "coordinates": [ "$lat", "$long" ]
    }
  }},
  { "$out": "newcollection" }
])

Ou même en utilisant $addFields pour simplement "ajouter" la nouvelle propriété aux documents :

db.collection.aggregate([
  { "$addFields": {
    "geometry": {
      "type": { "$literal": "Point" },
      "coordinates": [ "$lat", "$long" ]
    }
  }},
  { "$out": "newcollection" }
])

Si vous utilisez MongoDB 2.6 et supérieur, vous pouvez le faire avec le cadre d'agrégation et éviter de boucler les résultats dans votre programme client afin de créer une nouvelle collection.

La principale fonctionnalité ici qui vous aide est le $out Opérateur pour envoyer la sortie à une nouvelle collection. Mais aussi être un peu malin pour créer le tableau dont vous avez besoin.

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" }
])

Donc, cela utilise le $literal opérateur afin de spécifier un nouveau tableau en tête du pipeline. Cet opérateur placera le contenu dans la propriété du document exactement comment il est fourni. Donc, aucune substitution de variable n'est autorisée, donc "littérale".

Afin de créer le tableau "coordintes", nous déroulons simplement ce premier tableau qui crée essentiellement deux exemplaires de chaque document avec une valeur différente dans "type". Ceci est ensuite utilisé dans le $group étape conditionnellement $push soit la valeur "$lat" ou "$long" sur ce tableau.

Enfin, utilisez $project à nouveau pour finaliser la structure du document puis $out envoie toute la sortie à la nouvelle collection.

Notez que cela n'a de sens que si votre intention est de créer une nouvelle collection et d'éviter d'envoyer du trafic "sur le fil". Cela ne pourrait pas être utilisé uniquement dans le cadre d'agrégation pour remodeler votre document avec l'intention de faire ensuite une requête "géo-spatiale" dans ce même pipeline d'agrégation car les requêtes "géo-spatiales" ne fonctionneront que lorsqu'elles seront réellement indexées sur une collection .

Cela peut donc vous aider à créer une nouvelle collection comme vous le souhaitez, mais au moins cela sert d'exemple (ou deux exemples en fait) de la façon de créer un tableau à partir de différentes valeurs avec le cadre d'agrégation.