2016-11-28 5 views
1

カウントを表示するために複数のフィールドに集計を適用しようとしましたが、機能しません。Mongodb集計数が複数のフィールドでゼロ値で表示される

私は4つの異なる値を持っていると言うことができますvalue1、value2、value3、value4、value5これは固定値ではありません非常に繰り返し値です。その値を私の出力のような相対的な数で表示したいのですが、field2の値も表示し、出力結果をカウントする必要があります。私は、それはだ方法を知ってみましょう

{ 
"field1.value1" : 0 
} 
{ 
"field1.value2" : 1 
} 
{ 
"field1.value3" : 12 
} 
{ 
"field2.abc" : 50 
} 
{ 
"field2.xyz" : 5 
} 

:ここ

は私のクエリここ

db.Collection.aggregate([ 
    { $group: { 
    { 
     "_id": {field1:"$field1",field2:"$field2"} 
    } 
    }, 
    { 
    "count": { "$sum": 1 } 
    } 
]); 

は私のデータ

{ 
    "_id" : "1", 
    "field1" : "value1", 
    "field2" : "abc" 
} 
{ 
    "_id" : "2", 
    "field1" : "value2", 
    "field2" : "xyz" 
} 
{ 
    "_id" : "3", 
    "field1" : "value2", 
    "field2" : "abc" 
} 
{ 
    "_id" : "4", 
    "field1" : "value3", 
    "field2" : "abc" 
} 
{ 
    "_id" : "5", 
    "field1" : "value1", 
    "field2" : "xyz" 
} 
{ 
    "_id" : "6", 
    "field1" : "value3", 
    "field2" : "xyz" 
} 
{ 
    "_id" : "7", 
    "field1" : "value1", 
    "field2" : "abc" 
} 
{ 
    "_id" : "8", 
    "field1" : "value2", 
    "field2" : "xyz" 
} 
{ 
    "_id" : "9", 
    "field1" : "value1", 
    "field2" : "abc" 
} 
{ 
    "_id" : "10", 
    "field1" : "value1", 
    "field2" : "abc" 
} 
{ 
    "_id" : "11", 
    "field1" : "value2", 
    "field2" : "xyz" 
} 

で、私の出力はこれを好きにするとしています可能。

+0

あなたはより多くの理解のためのあなたのコレクションのいくつかのダミーデータを追加してくださいすることができます。 –

答えて

0

$ groupステージでは、複数のフィールドに_idを付けることができます。これにより、異なるフィールドの既存のすべての組み合わせに対するグループ化が作成されます。

まず、カウントフィールドとアキュムレータ 'sum'はグループステージ内にある必要があります。

db.collection.aggregate([ 
    { $group: { 
    { 
     "_id": { field1:"$field1", field2:"$field2" }, 
     "count": { "$sum": 1 } 
    } 
    } 
]); 

これで、クライアント側の結果を、少ない数のエントリで合計することができます。 「field1」と「field2」のユニークな値の数は元のドキュメントのセットと比較して非常に少ないので、これにはほとんど時間がかかりません。

私が考えることができる別のオプションは、複数の集約クエリを使用することですが、それはパフォーマンスによってはあなた次第です。

+0

私は1つの結果に2つのフィールド数を混在させたくありません。表示された結果出力ごとに分けることができれば良いでしょう。 – Meteor

+0

それが望ましいですが、私は単一の集約クエリを使用することは可能ではないと思います。集約ステージを通過すると、データが変換されるため、元のデータを元に戻して別のカウントを行うことはできません。 MapReduceを試してみることもできますが、これはこれに比べてはるかに遅くなります。 –

+0

あなたはそれについての質問を書いてください、私はMap-reduceについて考えていませんか? – Meteor

0

これは、3.4の$objectToArray演算子で行うことができます。

db.foo.aggregate([ 
    {$project: {x: {$objectToArray: "$$CURRENT"}}} 
    ,{$unwind: "$x"} 
    ,{$match: {"x.k": {$ne: "_id"}}} 
    ,{$group: {_id: {f:"$x.k", v: "$x.v"}, n: {$sum:1}}} 
    ,{$project: {fv: {$concat: [ "$_id.f", ".", "$_id.v" ]}, n:1, _id:0 }} 
        ]); 

これは任意の数のフィールドで動的に機能します。あなたはそれをやっているものを制限したい場合は、{$match: {"$x.k": {$ne: "fieldname you don't want"}}} これは、入力を与えられた上で掲載出力されます追加します。ここでは

{ "n" : 5, "fv" : "field2.xyz" } 
{ "n" : 4, "fv" : "field1.value2" } 
{ "n" : 2, "fv" : "field1.value3" } 
{ "n" : 6, "fv" : "field2.abc" } 
{ "n" : 5, "fv" : "field1.value1" } 

$arrayToObject「再合成」でドキュメントを使用することにより、正確なスペックを満たすソリューションです目的のフィールド名:降伏

db.foo.aggregate([ 
    {$project: {x: {$objectToArray: "$$CURRENT"}}} 
    ,{$unwind: "$x"} 
    ,{$match: {"x.k": {$ne: "_id"}}} 
    ,{$group: {_id: {f:"$x.k", v: "$x.v"}, n: {$sum:1}}} 
    ,{$project: { _id:0, xx: [ [ {$concat: ["$_id.f", ".", "$_id.v"]}, "$n"] ] }} 
    ,{$replaceRoot: { newRoot: {$arrayToObject: "$xx"}}} 
        ]); 

は:

{ "field2.xyz" : 5 } 
{ "field1.value2" : 4 } 
{ "field1.value3" : 2 } 
{ "field2.abc" : 6 } 
{ "field1.value1" : 5 } 
関連する問題