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.