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

ご覧のとおり、アクターは 2 番目のドキュメントで内部から外部に変更されています。私ができるようにしたいのは、アクターのタイプごとにインシデントの数を数えることです。私の最初の試みは次のようになりました:

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さんからのヒントを元に考えた答えです。アクターの値を見て、定義した isEmptyObject 関数を使用して、ドキュメントが空の JSON オブジェクトかどうかを確認する map 関数を作成します。次に、mapReduce を使用してコレクションを調べ、アクション フィールドが空かどうかを確認しました。オブジェクトが空でない場合は、キーの値を返すのではなく、内部または外部などの名前が付けられるキー自体を返します。

ここでの魔法は、私の isEmptyObject が mapReduce のスコープ内にあるようにする mapReduce のスコープ呼び出しでした。結果は、temp という名前のコレクションに書き込まれます。一時コレクションから必要な情報を収集したら、ドロップします。

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 に答える