0

有没有办法计算 mongodb 中的字段名称?我有一个 mongo 文档数据库,其中包含其他嵌入式文档。以下是数据可能看起来的示例。

{   
    "incident": "osint181",
    "summary":"Something happened",
    "actor": {
        "internal": {
            "motive": [
                "Financial"
            ],  
         "notes": "", 
        "role": [
            "Malicious"
        ],  
        "variety": [
            "Cashier"
        ]   
        }   
    }   
}   

另一个文档可能如下所示:

{   
    "incident": "osint182",
    "summary":"Something happened",
    "actor": {
        "external": {
            "motive": [
                "Financial"
            ],  
         "notes": "", 
        "role": [
            "Malicious"
        ],  
        "variety": [
            "Hacker"
        ]   
        }   
    }   
}   

如您所见,演员在第二个文档中已从内部更改为外部。我想做的是计算每种类型演员的事件数量。我的第一次尝试是这样的:

db.public.aggregate( { $group : { _id : "$actor", count : { $sum : 1 }}} );

但这给了我整个子文档,并且计数反映了有多少文档完全相同。相反,我希望获得内部计数和外部计数等。有没有一种优雅的方法可以做到这一点?如果不优雅,有人可以给我一个肮脏的方式吗?

4

2 回答 2

1

此类问题的最佳选择是使用 mongoDB 的 map-reduce ,它将允许您遍历 mongoDB 文档的所有键,并且可以轻松添加复杂的逻辑。在此处查看 map reduce 示例:http: //docs.mongodb.org/manual/applications/map-reduce/

于 2013-03-29T19:01:44.073 回答
1

这是我根据 Devesh 的提示得出的答案。我创建了一个 map 函数,它查看 actor 的值并使用我定义的 isEmptyObject 函数检查文档是否为空 JSON 对象。然后我使用 mapReduce 遍历集合并检查操作字段是否为空。如果对象不为空,那么我不会返回键的值,而是返回键本身,该键将被命名为内部、外部或其他名称。

The magic here was the scope call in mapReduce which makes it so that my isEmptyObject is in scope for mapReduce. The results are written to a collection which I named temp. After gathering the information I want from the temp collection, I drop it.

var isEmptyObject = function(obj) {
    for (var name in obj) {
        return false;
    }   
    return true;
};  

var mapFunction = function() {
    if (isEmptyObject(this.action)) {
        emit("Unknown",1); }
    else { 
        for (var key in this.actor) { emit(key,1); } } };

var reduceFunction = function(inKeys,counter) {
    return Array.sum(counter); };

db.public.mapReduce(mapFunction, reduceFunction, {out:"temp", scope:{isEmptyObject:isEmptyObject}} );

foo = db.temp.aggregate(
    { $sort : { value : -1 }});

db.temp.drop();
printjson(foo)
于 2013-03-31T23:30:05.233 回答