3

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

我写了一个日志,它将每个 php 错误保存在 MongoDB 集合中。读出错误不是问题,使用简单的 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° 的不同,而且切换非常困难。

4

1 回答 1

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)
        }
    ]
}

数组结构还使索引和查询更加直接。索引能够索引数组值,而且 MongoDB 还可以轻松地查询数组。例如,您可以使用$elemMatch灵活地查询特定错误(可能是代码和文件的组合) 。此外,由于errors是一个实数数组,您可以使用各种更新运算符,例如$pushor $pull

要考虑的一件事是嵌套对象限制了索引和编写查询的方式。在您之前的示例中,查询第一条错误消息的唯一方法是 by Errors.2048.0.Message,但使用上面的模式将允许查询errors.message.

数组还使聚合框架成为您可行的选择,特别是因为它允许您使用其运算符遍历数组,$unwind然后遍历$group数组元素中的值。除了有关聚合框架的 MongoDB 文档之外,您可能会发现此演示文稿很有帮助,直观地介绍了不同的运算符。

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

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

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

于 2013-06-24T19:52:55.080 回答