MongoDB RecursiveFind with Projection

时间:2016-10-14 19:33:25

标签: mongodb

我有一个递归的mongo文档结构,它是“事件”的层次结构:

{   
    "request": "open|casetype", 
    "datetime": ISODate("2013-10-10T23:06:37.000Z"),
    "type": "pageload",
    "totaltime": 4000,
    "serverTime": 3000,
    "clientTime": 1000,
    "cpuTime" : "2000",
    "externalTime" : "500",
    "dbTime": "500", 

    "events":[
        {

            "type": "interaction",  
            "label": "interaction 1 - load",
            "time": "2000",
            "events" :[{
                "type": "method",  
                "label": "test method",
                "time": "1000",
                "events" :[
                    { "type": "dbquery", "sql": "select * from x", "time":"100"},
                    { "type": "connector", "connectorName": "Google", "time":"200"},
                    {
                        "type":"method",
                        "label":"another method",
                        "time":800,
                        "events":[
                            { "type": "dbquery", "sql": "select * from y", "time":"500"}
                        ]
                    }

                ]
            } ]
        }
    ]
}

我希望能够运行查找和分组不同类型事件的查询。例如。查找给定dbquery或连接器的平均时间。通过connectorName对连接器进行分组并获取计数等

使用以下(我在StackOverflow上找到),我可以在文档中的任何位置找到type =“X”的完整文档:

db.pageloads.find(
  function () {
    var findKey = "type",
        findVal = "dbquery";

    function inspectObj(doc) {
      return Object.keys(doc).some(function(key) {
        if ( typeof(doc[key]) == "object" ) {
          return inspectObj(doc[key]);
        } else {
          return ( key == findKey && doc[key] == findVal );
        }
      });
    }
    return inspectObj(this);
  }
)

然而,我真正想要的只是包含映射的子文档,然后我可以对其进行聚合。我不确定此时我的问题是查找本身还是文档结构之一。

1 个答案:

答案 0 :(得分:0)

作为变种,您可以使用自定义查询功能。

这是查找平均时间的示例。 将下面的代码放在 query.js 文件中:

(function() {
    var cursor = db.pageloads.find(),
        result = [],
        findKey = 'type',
        findVal = 'dbquery',
        findParam = 'time';

    function average(data) {
        return sum(data) / data.length;
    }

    function sum(data) {
        var sum = 0;
        for (var i = 0; i < data.length; i++) {
            sum += parseInt(data[i], 10);
        }

        return sum;
    }

    while (cursor.hasNext()) {
        function filter(current) {
            for (var item in current) {
                if (typeof(current[item].events) === 'object') {
                    var next = current[item].events;
                    delete current[item].events;
                }
                if (typeof(current[item][findKey]) !== 'undefined' && current[item][findKey] === findVal) {
                    result.push(current[item][findParam]);
                }
            }
            if (typeof(next) !== 'undefined') {
                filter(next);
            };
        }
        filter(cursor.next().events);
    };

    return average(result); // You can use sum or other function
})();

并运行:

mongo your_database < query.js --quiet

您可以通过更改参数和内部子功能来调整聚合逻辑。

当然,这不是一个干净的解决方案,但它总比没有好。