2016-05-12 1 views
0

MongoDBの新機能で、Aggregationを使用して次の問題を解決します。私はそのようなコレクションを持っています。MongoDB:値が配列であるフィールドからの値のカウント

{ 
"_id" : ObjectId("5732fa438acef72abc442ac8"), 
"publisherId" : NumberInt(1), 
"type" : NumberInt(3), 
"qualityInfo" : [ 
    "FilterOne", 
    "FilterTwo", 
    "FilterThree" 
], 
"date" : "2016-05-11 11:24:19" 
} 
{ 
    "_id" : ObjectId("5732fa438acef72abc442ac9"), 
    "publisherId" : NumberInt(3), 
    "type" : NumberInt(1), 
    "qualityInfo" : [ 
     "FilterOne", 
     "FilterFour" 
    ], 
    "date" : "2016-05-11 11:24:19" 
} 

私はqualityInfoフィールドの各値のれる発生し、出力に次のような結果に何かをカウントします。

{ 
"_id" : "FilterOne", 
"count" : "42" 
} 
{ 
    "_id" : "FilterTwo", 
    "count" : "30" 
} 
{ 
    "_id" : "FilterThree", 
    "count" : "12" 
} 
{ 
    "_id" : "FilterFour", 
    "count" : "43" 
} 

私は集約操作がMapReduceよりもはるかに高速であることを気づいたようAggregationを介してこれを実現することを好むだろう。私がそうでなければ私を修正してください。それで集約によってそれをすることは可能ですか?そうでない場合、私はすでにMapReduceクエリを次のように試みました。

db.myCollection.mapReduce(
function(){ 
    for(i = 0; i < this.qualityInfo.length; i++ ){ 
     emit(this.qualityInfo[i], null); 
    } 
}, 
function(names, vals){ 
    return Array.sum(names); 
}, 
{ query: { publisherId: 2 }, out: "qualityResult" } 

);

しかし、これは私にカウント値を与えません。 MapReduceの結果で、文字列を_idvalueの両方に返します。

答えて

1

mongodb集約を使用すると、1行の単純なコマンドです。

db.collection.aggregate([ 
    { $unwind:"$qualityInfo"}, 
    { $project: {"qualityInfo":1} }, 
    { $group:{ 
      _id:"$qualityInfo", 
      count: {$sum:1}}´ 
    } 
]); 
+0

このクエリは私に空の結果を与えています。ただ何も。 –

+0

私は問題があります。 '$ project'は' $ unwind'の前に来なければなりません。そして、私は最初の質問に「$一致」を持っています。それは動作します。ありがとうございました! –

+0

うれしいです。私の意見では、次の段階に行くのは単なるオプションなので、$ projectionは何の問題も起こらないはずです。ここには見えないものがあり、問題を引き起こしたものと$ matchがあると思います。 – AMITAVA

1

あなたはmap reduceを使用してほぼそこにいます。 使用以下の機能をマップ-削減:

db.myCollection.mapReduce(
function(){ 
    for(i = 0; i < this.qualityInfo.length; i++ ){ 
     emit(this.qualityInfo[i], 1); 
    } 
}, 
function(names, vals){ 
    return Array.sum(vals); 
}, 
{ query: { publisherId: 2 }, out: "qualityResult" } 
); 

をあなたはFILTERNAMEあたりの値として「1」を発することによって、あなたはあなたが得る、値でArray.sumを行うことにより

{_id: "filterOne", values[1,1,1]}, 
{_id: "filterTwo", values[1,1]} 

のような結果を得ます各フィルタの発生回数

+0

これは機能しました。どうもありがとうございました。しかし、私は800万以上の文書を持っており、この解決法は非常に遅いです。私はAMITAVAのAggregationクエリを使用していました。とにかくもう一度ありがとう。 :) –

関連する問題