2012-10-03 6 views
2

Cette question a deux parties. La structure de collecte est:Requête d'agrégat MongoDB équivalente à PostsgreSQL

_id: MongoId,
agent_id: string,
résultat: string,
created_on: ISO DATE,
... d'autres domaines ...

Première partie:
Sortie désirée: Un résultat pour chaque agent_id et combinaison de résultats avec un compte: Représentation TUPLE avec SQL équivalent en utilisant PostgreSQL. J'ai trouvé la requête mongo ci-dessous .... Je pense avoir une erreur conceptuelle ou syntaxique. Les docs disent d'utiliser $ match early in the pipeline:, mais bien que la correspondance de $ limite la requête quand je l'exécute toute seule, dès que j'ajoute le groupe $, j'obtiens beaucoup de résultats. Aussi, je n'arrive pas à comprendre comment regrouper par plus d'un domaine. Comment puis-je modifier la requête ci-dessous pour obtenir des résultats comme la requête SQL ci-dessus?

db.collection.aggregate(
    { $match : 
    { created_on: 
     { $gte: new Date('08-13-2012') //some arbitrary date 
    } 
    }, $group: 
    { _id:"$agent_id" }, 
    $project: 
    {_id:0, agent_id:1, result:1} 
}) 

Partie 2) Le premier jeu de résultats serait suffisant, mais pas optimale. Avec PostgreSQL je peux obtenir un résultat fixé comme:

("1234", { "Success", "Failure" }, { 4, 3 }), 
("4567", { "Success", "Failure" }, { 3, 0 }), 
("7896", { "Success", "Failure" }, { 0, 2 }) 

Je peux le faire en Postgresql avec le type de données de tableau et une fonction set_to_array (fonction personnalisée). Le SQL spécifique Pg est:

SELECT agent_id, set_to_array(result), set_to_array(count(*)) 
FROM table 
GROUP BY agent_id, result 
HAVING created_on >= now()::date; 

je crois que la structure de données équivalente à MongoDB ressemblerait à ceci:

[ 
    { "1234", [ { "success": 4 }, { "failure": 4 } ] }, 
    { "4567", [ { "success": 3 }, { "failure": 0 } ] }, 
    { "7896", [ { "success": 0 }, { "failure": 0 } ] } 
] 

Est-il possible d'obtenir ces résultats souhaités avec comprimées cadre global MongoDB?

Répondre

3

Ici, vous allez:

a créé des données de test:

db.test.insert ({agent_id: "1234", résultat: "échec", created_on: new Date()}) ; db.test.insert ({agent_id: "1234", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1234", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1234", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1234", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1234", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1234", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Success", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()}); db.test.insert ({agent_id: "1324", résultat: "Failure", created_on: new Date()});

db.test.aggregate(
    { 
    $match:{ /* filter out the things you want to aggregate */ 
     created_on:{$gte:new Date(1000000)} 
    } 
    }, 
    { 
    $group: {_ 
     _id: { /* the things you want to group on go in the _id */ 
     agent_id:"$agent_id", 
     result:"$result" 
     }, 
     count:{$sum:1} /* simple count */ 
    } 
    }, 
    { 
    $project: { /* take the id out into the separate fields for your tuple. */ 
     _id:0, 
     agent_id:"$_id.agent_id", 
     result:"$_id.result", 
     count:"$count" 
    } 
    }); 

donne:

{ 
"result" : [ 
    { 
     "count" : 7, 
     "agent_id" : "1324", 
     "result" : "Failure" 
    }, 
    { 
     "count" : 4, 
     "agent_id" : "1324", 
     "result" : "Success" 
    }, 
    { 
     "count" : 4, 
     "agent_id" : "1234", 
     "result" : "Success" 
    }, 
    { 
     "count" : 3, 
     "agent_id" : "1234", 
     "result" : "Failure" 
    } 
], 
"ok" : 1 
} 

Ajout partie 2 - assez similaire à la partie 1, mais le comptage est un peu plus compliqué; Fondamentalement, vous ne comptez que si elle correspond à ce que vous voulez compter:

db.test.aggregate(
    { 
    $match: { 
     created_on: {$gte:new Date(1000000)} 
    } 
    }, 
    { 
    $group: { 
     _id: { 
     agent_id:"$agent_id" 
     }, 
     failure: { 
     $sum:{ 
      $cond:[ 
      {$eq:["$result","Failure"]}, 
      1, 
      0 
      ] 
     } 
     }, 
     success: { 
     $sum: { 
      $cond:[ 
      {$eq:["$result","Success"]}, 
      1, 
      0 
      ] 
     } 
     } 
    } 
    }, 
    { 
    $project: { 
     _id: 0, 
     agent_id: "$_id.agent_id", 
     failure: "$failure", 
     success: "$success" 
    } 
    }); 

donne:

{ 
"result" : [ 
    { 
     "failure" : 7, 
     "success" : 4, 
     "agent_id" : "1324" 
    }, 
    { 
     "failure" : 3, 
     "success" : 4, 
     "agent_id" : "1234" 
    } 
], 
"ok" : 1 
} 
+0

Est-il possible de se détendre pour obtenir un « grand total »? J'ai été en mesure d'ajouter des sous-totaux à chaque résultat (somme des échecs et succès), mais je ne suis pas sûr si la production d'un enregistrement qui totalise tous les succès et les échecs d'agent est possible dans la requête elle-même. – Ketema

+0

Vous voulez dire dans la même requête, ou dans une nouvelle requête? –

+0

il serait intéressant si résultat pourrait avoir un grand total dans la même requête, pas sûr si c'est possible cependant. – Ketema

Questions connexes