2013-06-06 4 views
3

J'ai utilisé MySQL depuis que j'étais un jeune garçon et maintenant je dois passer à MongoDB pour diverses raisons. J'écris un journal qui enregistre toutes les erreurs PHP dans une collection MongoDB. La lecture des erreurs n'est pas le problème, en utilisant un simple find() est assez facile et c'est génial que vous puissiez utiliser les tableaux php pour accéder aux données.Chaînes PHP/MongoDB Count dans un tableau utilisant des agrégations

Maintenant, je veux avoir des statistiques sur les erreurs. Ma collection ressemble à ceci:

{ 
    "_id": ObjectId("51af10ca0e5e723c0a000000"), 
    "Errors": { 
    "2048": { 
     "0": { 
     "Message": "Declaration of ADODB_mysqli::MetaIndexes() should be compatible with ADOConnection::MetaIndexes($table, $primary = false, $owner = false)", 
     "File": "File.php", 
     "Line": NumberInt(29), 
     "Time": NumberInt(1370427591) 
     } 
    }, 
    "2": { 
     "0": { 
     "Message": "Error", 
     "File": "File.php", 
     "Line": NumberInt(29), 
     "Time": NumberInt(1370427591) 
     }, 
     "1": { 
     "Message": "Error", 
     "File": "File.php", 
     "Line": NumberInt(29), 
     "Time": NumberInt(1370427591) 
     } 
    }, 
    "8": { 
     "0": { 
     "Message": "Undefined index: PluginLastAdded", 
     "File": "File.php", 
     "Line": NumberInt(36), 
     "Time": NumberInt(1370427594) 
     }, 
     "1": { 
     "Message": "Undefined index: PluginLastAdded", 
     "File": "File.php", 
     "Line": NumberInt(36), 
     "Time": NumberInt(1370427594) 
     } 
    } 
    } 
} 

Maintenant je veux savoir à quelle fréquence chaque erreur dans cette entrée apparaît. Ce serait bien d'avoir une liste séparée en 2048, 2, 8 et ensuite le compte de chaque erreur. Est-ce possible sans trop de code PHP mais en utilisant l'agrégation de MongoDB?

Toute aide serait géniale, MongoDB est à 180 ° différent de MySQL selon moi, et le switch est assez dur.

+0

Un problème que je peux est votre schéma, vous ne pouvez pas facilement décompresser et agréger ce schéma, sauf avec une carte réduire. Je vous recommande personnellement de le changer afin que le code d'erreur ne soit pas la clé mais plutôt un champ dans le document – Sammaye

+0

Merci, je vais essayer de cette façon. Peut-être que je peux venir à travers une solution maintenant. :) – Moe

Répondre

1

Pour construire sur ce Sammaye mentionné ci-dessus, le schéma suivant avec des tableaux réels serait plus approprié:

{ 
    "_id": ObjectId("51af10ca0e5e723c0a000000"), 
    "errors": [ 
     { 
      "code": 2048, 
      "message": "Declaration of ADODB_mysqli::MetaIndexes() should be compatible with ADOConnection::MetaIndexes($table, $primary = false, $owner = false)", 
      "file": "File.php", 
      "line": NumberInt(29), 
      "time": NumberInt(1370427591) 
     }, 
     { 
      "code": 2, 
      "message": "Error", 
      "file": "File.php", 
      "line": NumberInt(29), 
      "time": NumberInt(1370427591) 
     }, 
     { 
      "code": 2, 
      "message": "Error", 
      "file": "File.php", 
      "line": NumberInt(29), 
      "time": NumberInt(1370427591) 
     }, 
     { 
      "code": 8, 
      "message": "Undefined index: PluginLastAdded", 
      "file": "File.php", 
      "line": NumberInt(36), 
      "time": NumberInt(1370427594) 
     }, 
     { 
      "code": 8, 
      "message": "Undefined index: PluginLastAdded", 
      "file": "File.php", 
      "line": NumberInt(36), 
      "time": NumberInt(1370427594) 
     } 
    ] 
} 

La structure de tableau fait également l'indexation et l'interrogation beaucoup plus simple. Les index sont capables d'indexer array values, et MongoDB facilite également les requêtes sur les tableaux. Par exemple, vous avez la possibilité de rechercher des erreurs particulières (peut-être une combinaison de code et de fichier) avec $elemMatch. En outre, puisque errors est un tableau réel, vous pouvez utiliser divers update operators, tels que $push ou $pull. Une chose à considérer est que les objets imbriqués limitent la façon dont vous indexez et écrivez des requêtes. Dans votre exemple précédent, le seul moyen d'interroger le premier message d'erreur est de Errors.2048.0.Message, mais l'utilisation du schéma ci-dessus permet d'effectuer une requête sur errors.message.

tableaux fait également Aggregation Framework une option viable pour vous, en particulier, car il vous permettra de itérer tableaux avec son opérateur $unwind puis $group sur des valeurs dans les éléments du tableau. En plus de la documentation MongoDB sur le cadre d'agrégation, vous pouvez trouver this presentation utile, passe par les différents opérateurs visuellement.

Pour votre question précédente sur l'obtention d'un décompte du nombre d'erreurs par code, le pipeline cadre d'agrégation suivant calculerait que dans tous les documents de la collection:

db.foo.aggregate([ 
    { $unwind: "$errors" }, 
    { $group: { 
     _id: "$errors.code", 
     num: { $sum: 1 } 
    }} 
]); 

Enfin, je suggère le stockage de la time champ en tant que date BSON (MongoDate en PHP) au lieu d'un nombre entier. Cela ouvre la possibilité d'utiliser date operators dans le cadre d'agrégation.

Questions connexes