2015-09-15 6 views
1

Je suis coincé et confondu avec mon expression agrégée actuelle et j'espérais sur une entrée ou une solution dans Mongo lui-même.groupe d'agrégats mongo avec groupe interne/compte sur tableau

Les données d'origine de Mongo (simplifié aux seuls domaines dont j'ai besoin en ce moment):

[{ 
    'status': 'Cancelled', 
    'CIC Package': 'Test Gallery Cafe', 
}, 
{ 
    'status': 'Completed', 
    'CIC Package': 'Design Thinking workshop' 
}, 
{ 
    'status': 'Tentative', 
    'CIC Package': 'Design Thinking workshop' 
}, 
{ 
    'status': 'Confirmed', 
    'CIC Package': 'Product/solution demonstration' 
}, 

....etc 
] 

En général ... il y a 1000s des dossiers de probablement 8 'packages CIC avec des statuts différents (Confirmé , Annulé, Tentative, Complété) et d'autres données que j'ai exclues pour le moment.

Le résultat final Je cherche quelque chose comme ceci:

[{ 
    "_id" : "Test Gallery Café", 
    "package" : "Test Gallery Café", 
    "status" : [ 
     { 
     "Cancelled": 1 
     }, 
     { 
     "Completed": 1 
     } 
    ] 
    }, 
    { 
    "_id" : "Design Thinking workshop", 
    "package" : "Design Thinking workshop", 
    "status" : [ 
     { 
     "Cancelled": 3 
     }, 
     { 
     "Completed": 2 
     } 
    ] 
    }, 
    { 
    "_id" : "Product/solution demonstration", 
    "package" : "Product/solution demonstration", 
    "status" : [ 
     { 

     "Completed": 10 
     }, 
     { 
     "Cancelled": 3 
     }, 
     { 
     "Confirmed": 1 
     } 
    ] 
    }] 

donc par CIC package que je retitré à package dans le $group je veux avoir un compte de chaque situation qui existe dans l'ensemble de données. Les statuts et les paquets ne sont pas sous mon contrôle, donc au fil du temps de nouveaux pourraient être ajoutés. Il doit être un groupe dynamique.

Je suis venu aussi loin que cela:

db.reportData.aggregate([ 
    { 
    $project: 
    { 
     'CIC package': 1, 
     'Status': 1 
    } 
    } 
, 
    { 
    $group: 
    { 
     _id: '$CIC package', 
     package: 
     { 
     $first: '$CIC package' 
     } 
    , 
     status: 
     { 
     $push: '$Status' 
     } 
    } 
    } 
]).toArray() 

qui a abouti à quelque chose aime ceci:

[{ 
    "_id" : "Test Gallery Café", 
    "package" : "Test Gallery Café", 
    "status" : [ 
     "Cancelled", 
     "Completed" 
    ] 
    }, 
    { 
    "_id" : "Design Thinking workshop", 
    "package" : "Design Thinking workshop", 
    "status" : [ 
     "Cancelled", 
     "Cancelled", 
     "Cancelled", 
     "Completed", 
     "Completed" 
    ] 
    }, 
    { 
    "_id" : "Product/solution demonstration", 
    "package" : "Product/solution demonstration", 
    "status" : [ 
     "Completed", 
     "Completed", 
     "Cancelled", 
     "Processing", 
     "Cancelled", 
     "Cancelled", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Completed", 
     "Tentative" 
    ] 
    }] 

Ceci est une petite extraction d'un ensemble beaucoup plus vaste, mais un bon échantillon de la résultat jusqu'à présent.

J'ai essayé unwind après le dernier group qui crée de nouveaux enregistrements que je pourrais encore group, mais je suis un peu confus en ce moment. Et peut-être que je le fais inefficacement. Je pense que je suis presque là mais j'aimerais beaucoup une entrée.

Des idées?

+0

Votre pipeline d'agrégation fait référence à plusieurs champs non présents dans votre échantillon de données. S'il vous plaît montrer vos données réelles et le résultat souhaité. –

+0

Les données réelles sont privées, mais je pense que j'ai montré les données sous la table d'origine. Les seuls champs importants sont 'SIS package' et 'Status'. Le principal problème que j'ai est l'ensemble de données supérieur dans mon message, il montre tous les statuts par paquet, mais j'ai besoin d'avoir un compte de chaque statut par paquet. C'est une chose assez complexe à écrire. Je ne sais pas comment le rendre plus clair. – Mattijs

+0

Vous pouvez le rendre plus clair en vous référant à des champs comme "paquet" qui est présent dans vos données et non pas "paquet SIS" ou l'inverse. Notamment vous faites référence à "Date de début" qui n'a aucun équivalent du tout. Si vous en faites trop abstraction dans ce que vous demandez, vous courez le risque que la réponse ne corresponde pas à vos besoins de données. Ou nous courons le risque de beaucoup de communication avec vous parce que vous ne comprenez pas. S'il vous plaît, effacez-le afin que vous demandiez ce dont vous avez réellement besoin. –

Répondre

2

Vous semblez essentiellement vouloir le « compte de l'état » pour chaque type, ce qui est une question de regrouper d'abord compter ceux et seulement par le _id primaire de l'objet:

db.reportData.aggregate([ 
    { "$unwind": "$status" }, 
    { "$group": { 
     "_id": { 
      "_id": "$_id", 
      "package": "$package", 
      "status": "$status" 
     }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$group": { 
     "_id": "$_id._id", 
     "package": { "$first": "$_id.package" }, 
     "status": { 
      "$push": { 
       "$cond": [ 
        { "$eq": [ "$_id.status", "Completed" ] }, 
        { "Completed": "$count" }, 
        { "$cond": [ 
         { "$eq": [ "$_id.status", "Cancelled" ] }, 
         { "Cancelled": "$count" }, 
         { "$cond": [ 
          { "$eq": [ "$_id.status", "Processing" ] }, 
          { "Processing": "$count" }, 
          { "Tentative": "$count" } 
         ]} 
        ]} 
       ] 
      } 
     } 
    }} 
]) 

Ou il suffit de garder générique avec un champ « type » pour chaque état des résultats:

db.reportData.aggregate([ 
    { "$unwind": "$status" }, 
    { "$group": { 
     "_id": { 
      "_id": "$_id", 
      "package": "$package", 
      "status": "$status" 
     }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$group": { 
     "_id": "$_id._id", 
     "package": { "$first": "$_id.package" }, 
     "status": { 
      "$push": { 
       "type": "$_id.status", 
       "count": "$count" 
      } 
     } 
    }} 
]) 

qui vous donnera des résultats comme celui-ci:

{ 
     "_id" : "Test Gallery Café", 
     "package" : "Test Gallery Café", 
     "status" : [ 
       { 
         "type" : "Completed", 
         "count" : 1 
       }, 
       { 
         "type" : "Cancelled", 
         "count" : 1 
       } 
     ] 
} 
{ 
     "_id" : "Design Thinking workshop", 
     "package" : "Design Thinking workshop", 
     "status" : [ 
       { 
         "type" : "Completed", 
         "count" : 2 
       }, 
       { 
         "type" : "Cancelled", 
         "count" : 3 
       } 
     ] 
} 
{ 
     "_id" : "Not specified", 
     "package" : "Not specified", 
     "status" : [ 
       { 
         "type" : "Processing", 
         "count" : 1 
       }, 
       { 
         "type" : "Tentative", 
         "count" : 1 
       }, 
       { 
         "type" : "Cancelled", 
         "count" : 3 
       }, 
       { 
         "type" : "Completed", 
         "count" : 11 
       } 
     ] 
} 

Cela devient un peu mieux dans les prochaines versions de MongoDB avec $filter:

db.reportData.aggregate([ 
    { "$project": { 
     "package": 1, 
     "statusComplete": { 
      "$size": { 
       "$filter": { 
        "input": "$status", 
        "as": "el", 
        "cond": { 
         "$eq": [ "$$el", "Completed" ] 
        } 
       } 
      } 
     }, 
     "statusCancelled": { 
      "$size": { 
       "$filter": { 
        "input": "$status", 
        "as": "el", 
        "cond": { 
         "$eq": [ "$$el", "Cancelled" ] 
        } 
       } 
      } 
     } 
    }} 
]) 

Comme il est essentiellement de « compter les éléments correspondants dans les tableaux », et la dernière pourrait être développée à en fait produire le même résultat de tableau que le premier, avec beaucoup moins de frais généraux en raison de $unwind. Mais bien sûr, cela doit encore être publié, mais ce n'est qu'un échantillon de ce que vous pourrez faire à l'avenir.

également pour l'enregistrement, les données présentées dans le poste d'origine avant la modification était le suivant:

{ 
     "_id" : "Test Gallery Café", 
     "package" : "Test Gallery Café", 
     "status" : [ 
       "Cancelled", 
       "Completed" 
     ] 
} 
{ 
     "_id" : "Design Thinking workshop", 
     "package" : "Design Thinking workshop", 
     "status" : [ 
       "Cancelled", 
       "Cancelled", 
       "Cancelled", 
       "Completed", 
       "Completed" 
     ] 
} 
{ 
     "_id" : "Not specified", 
     "package" : "Not specified", 
     "status" : [ 
       "Completed", 
       "Completed", 
       "Cancelled", 
       "Processing", 
       "Cancelled", 
       "Cancelled", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Completed", 
       "Tentative" 
     ] 
} 
+0

Merci d'avoir regardé cela. Peut-être que c'est un peu plus clair maintenant que j'ai modifié ma question, mais je ne voudrais pas coder en dur les statuts parce que je n'ai aucun contrôle sur eux. Actuellement, il y en a 6, mais cela pourrait changer dans le futur. Le paquet est à, ils pourraient ajouter de nouveaux paquets à leur système. J'ai implémenté la première partie de votre groupe $ qui crée les statuts par paquet en tant que lignes séparées et maintenant je dois le regrouper en paquets avec un tableau de tous ses états et leurs comptes respectifs. :) soupir – Mattijs

+0

@ Mattijs Je pense que votre "edit" a rendu les choses encore plus obscures que la question était de commencer. Au moins cela a montré une source qui pourrait arriver à votre résultat attendu (comme le fait le code ici), mais maintenant, il est complètement difficile de savoir comment y arriver. –

+0

Vous plaisantez ... Eh bien, je ne suis pas d'accord. Je veux juste arriver au résultat final tel qu'affiché dans le deuxième bloc de code. Je suis presque là avec une partie de votre solution, seulement je ne peux pas faire la partie $ cond parce que les statuts doivent être comptés dynamiquement. Je suis juste en train de trouver comment faire le deuxième et dernier $ groupe pour obtenir le résultat final que je veux: par paquet a un objet tableau d'objets d'état avec les comptes. En MYSQL je n'aurais aucun problème à le faire mais à Mongo je deviens complètement confus. Peut-être que je devrais appeler ça un jour. Demain pourrait apporter une nouvelle idée – Mattijs

1

D'accord,

Je suis venu pour trier une solution avec l'aide de la réponse Blakes Seven. La requête suivante semble fonctionner et est basée sur l'ensemble de données de début affiché dans ma première question. L'addition ajoute 2 groupes à la fin pour créer le résultat désiré.

 db.reportData.aggregate([ 
     { 
     $project: { 
      'CIC package': 1, 
      'Start Date': 1, 
      'Status': 1 
     } 
     }, 
     { 
     $group: { 
      _id: '$CIC package', 
      package: { 
      $first: '$CIC package' 
      }, 
      status: { 
      $push: '$Status' 
      } 
     } 
     }, 
     { 
     $unwind: '$status' 
     }, 
     { 
     $group: 
     { 
      _id: 
      { 
      "_id": "$_id", 
      "package": "$package", 
      "status": "$status" 
      }, 
      package: { 
      $first: '$package' 
      }, 
      status: { 
      $first: '$status' 
      }, 
      count:{ 
      $sum: 1 
      } 

     } 

     }, 
     { 
     $group: 
     { 
      _id: "$_id._id", 
      package: { 
      $first: "$_id.package" 
      }, 
      status: 
      { 
      $push: 
      { 
       "status" : "$_id.status", 
       "count": '$count' 

      } 
      } 
     } 
     } 
    ]).toArray() 

Il en résulte un ensemble de données comme ceci:

[ 
     { 
     "_id" : "Studio Canal", 
     "package" : "Studio Canal", 
     "status" : [ 
      { 
      "status" : "Completed", 
      "count" : 8 
      }, 
      { 
      "status" : "Cancelled", 
      "count" : 2 
      } 
     ] 
     }, 
     { 
     "_id" : "Meeting/forum", 
     "package" : "Meeting/forum", 
     "status" : [ 
      { 
      "status" : "Cancelled", 
      "count" : 254 
      }, 
      { 
      "status" : "Completed", 
      "count" : 275 
      }, 
      { 
      "status" : "Processing", 
      "count" : 6 
      }, 
      { 
      "status" : "Tentative", 
      "count" : 1 
      }, 
      { 
      "status" : "Confirmed", 
      "count" : 6 
      } 
     ] 
     }, 
     { 
     "_id" : "Design Thinking workshop", 
     "package" : "Design Thinking workshop", 
     "status" : [ 
      { 
      "status" : "Cancelled", 
      "count" : 2 
      } 
     ] 
     }, 
     { 
     "_id" : "Test Gallery Café", 
     "package" : "Test Gallery Café", 
     "status" : [ 
      { 
      "status" : "Cancelled", 
      "count" : 1 
      }, 
      { 
      "status" : "Completed", 
      "count" : 1 
      } 
     ] 
     }, 
     { 
     "_id" : "Not specified", 
     "package" : "Not specified", 
     "status" : [ 
      { 
      "status" : "Completed", 
      "count" : 124 
      }, 
      { 
      "status" : "Tentative", 
      "count" : 1 
      }, 
      { 
      "status" : "Cancelled", 
      "count" : 42 
      }, 
      { 
      "status" : "Confirmed", 
      "count" : 4 
      }, 
      { 
      "status" : "Processing", 
      "count" : 5 
      } 
     ] 
     }, 
     { 
     "_id" : "Customer/partner/special event", 
     "package" : "Customer/partner/special event", 
     "status" : [ 
      { 
      "status" : "Tentative", 
      "count" : 1 
      }, 
      { 
      "status" : "Cancelled", 
      "count" : 145 
      }, 
      { 
      "status" : "Processing", 
      "count" : 3 
      }, 
      { 
      "status" : "Completed", 
      "count" : 284 
      }, 
      { 
      "status" : "Confirmed", 
      "count" : 8 
      } 
     ] 
     }, 
     { 
     "_id" : "Product/solution demonstration", 
     "package" : "Product/solution demonstration", 
     "status" : [ 
      { 
      "status" : "Tentative", 
      "count" : 1 
      }, 
      { 
      "status" : "Confirmed", 
      "count" : 4 
      }, 
      { 
      "status" : "Cancelled", 
      "count" : 82 
      }, 
      { 
      "status" : "Completed", 
      "count" : 130 
      }, 
      { 
      "status" : "Processing", 
      "count" : 1 
      } 
     ] 
     } 
    ] 

qui est ce que je cherche. Je dois vérifier maintenant si les données sont correctes mais ça ressemble à ça. Seule la question est maintenant/devrais-je l'optimiser. Peut-être quelque chose pour demain.