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

Clés dynamiques après $group by

Non pas que je pense que ce soit une bonne idée et surtout parce que je ne vois aucune "agrégation" ici, c'est qu'après "regroupement" pour ajouter à un tableau, vous de même $push tout ce contenu dans le tableau par le "status" clé de regroupement puis conversion en clés d'un document dans un $replaceRoot avec $arrayToObject :

db.collection.aggregate([
  { "$group": {
    "_id": "$status",
    "data": { "$push": "$$ROOT" }
  }},
  { "$group": {
    "_id": null,
    "data": {
      "$push": {
        "k": "$_id",
        "v": "$data"
      }
    }
  }},
  { "$replaceRoot": {
    "newRoot": { "$arrayToObject": "$data" }
  }}
])

Renvoie :

{
        "inProgress" : [
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5776"),
                        "status" : "inProgress",
                        "description" : "inProgress..."
                }
        ],
        "completed" : [
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5773"),
                        "status" : "completed",
                        "description" : "completed..."
                }
        ],
        "pending" : [
                {
                        "_id" : ObjectId("5b18d14cbc83fd271b6a157c"),
                        "status" : "pending",
                        "description" : "You have to complete the challenge..."
                },
                {
                        "_id" : ObjectId("5b18d31a27a37696ec8b5775"),
                        "status" : "pending",
                        "description" : "pending..."
                }
        ]
}

Cela pourrait être bien SI vous avez en fait "agrégé" au préalable, mais sur n'importe quelle collection de taille pratique, tout ce qui est en train de faire est d'essayer de forcer l'ensemble de la collection dans un seul document, et cela risque de briser la limite BSON de 16 Mo, donc je ne recommanderais même pas d'essayer cela sans " groupement" autre chose avant cette étape.

Franchement, le même code suivant fait la même chose, et sans astuces d'agrégation et sans problème de limite BSON :

var obj = {};

// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d => {
  if (!obj.hasOwnProperty(d.status))
    obj[d.status] = [];
  obj[d.status].push(d);
})

printjson(obj);

Ou un peu plus court :

var obj = {};

// Using forEach as a premise for representing "any" cursor iteration form
db.collection.find().forEach(d => 
  obj[d.status] = [ 
    ...(obj.hasOwnProperty(d.status)) ? obj[d.status] : [],
    d
  ]
)

printjson(obj);

Les agrégations sont utilisées pour la "réduction des données" et tout ce qui consiste simplement à "remodeler les résultats" sans réellement réduire les données renvoyées par le serveur est généralement mieux géré dans le code client de toute façon. Vous retournez toujours toutes les données, quoi que vous fassiez, et le traitement client du curseur a considérablement moins de surcharge. Et AUCUNE restriction.