PHP / MongoDB使用聚合计算数组中的字符串

时间:2013-06-06 12:26:59

标签: php mongodb aggregation-framework

我从小就使用MySQL,现在由于种种原因我不得不切换到MongoDB。

我写了一个日志,它保存了MongoDB集合中的每个php错误。读出错误不是问题,使用简单的find()非常简单,你可以使用php数组来获取数据。

现在我想了解一些有关错误的统计数据。我的收藏如下:

 {
   "_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)   
      }
    }
  }
}

现在我想知道此条目中的每个错误发生的频率。将分离列表分成2048,2,8,然后计算每个错误的数量会很棒。

这可能没有太多的PHP代码但使用MongoDB的聚合吗?

任何帮助都会很棒,我认为MongoDB与MySQL的差异是180°,而且转换非常困难。

1 个答案:

答案 0 :(得分:1)

基于Sammaye上面提到的内容,以下使用真实数组的模式会更合适:

{
    "_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)
        }
    ]
}

数组结构也使索引和查询更加直接。索引能够索引array values,而MongoDB也可以轻松查询数组。例如,您可以灵活地使用$elemMatch查询特定错误(可能是代码和文件的组合)。此外,由于errors是真实数组,因此您可以使用各种update operators,例如$push$pull

要考虑的一件事是嵌套对象限制了索引和编写查询的方式。在上一个示例中,查询第一条错误消息的唯一方法是Errors.2048.0.Message,但使用上面的架构可以在errors.message上进行查询。

Arrays也使Aggregation Framework成为可行的选项,特别是因为它允许您使用$unwind运算符迭代数组,然后对数组元素中的值进行$group。除了关于聚合框架的MongoDB文档之外,您可能会发现this presentation很有帮助,可以直观地浏览不同的运算符。

对于您之前关于获取每个代码的错误数量计数的问题,以下聚合框架管道将计算整个集合中所有文档的数据:

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

最后,我建议将time字段存储为BSON日期(PHP中为MongoDate)而不是整数。这开辟了在聚合框架中使用date operators的选项。