|
based on v41 Mongoには、 count, distinct と group by 操作をサーバーサイドで実行するファンクションがあります。 さらに集約をするために MapReduce を使うこともできます。 countcount() は、コレクション内で、クエリーにマッチするオブジェクトの件数を返します。ドキュメントセレクターが渡された場合、マッチするドキュメントの件数が返されます。 size() は count() と似ていますが、 limit() と skip() をクエリーで指定することができます。 db.collection.count(selector); 例: print( "# of objects: " + db.mycollection.count() ); print( db.mycollection.count( {active:true} ); count は、セレクターで使われている条件にインデックスがある場合速いです。たとえば、 active でのcountを速くするためには、 db.mycollection.ensureIndex( {active:1} );
distinctdistinct(key) は 与えられた key のdistinctな値を返します。 distinctコマンドは、コレクション内で与えられたキーにマッチするdistinctな値を返します。 このコマンドは次の形式を取ります { distinct : <collection_name>, key : <key>[, query : <query>] }
多くのドライバーはdistinct用のヘルパーがありますが。 > db.addresses.save({"zip-code": 10010})
> db.addresses.save({"zip-code": 10010})
> db.addresses.save({"zip-code": 99701})
> // シェルヘルパー
> db.addresses.distinct("zip-code");
[ 10010, 99701 ]
distinct は、ネストされたキーも指定できます > db.comments.save({"user": {"points": 25}})
db.comments.save({"user": {"points": 31}})
db.comments.save({"user": {"points": 25}})
> db.comments.distinct("user.points");
[ 25, 31 ]
また、distinctに他のクエリー条件を加えることもできます。 > db.address.distinct( "zip-code" , { age : 30 } )
注意: distinct コマンドは、一つのBSONオブジェクトとして返します。 もし、結果が大きい場合 (4メガバイト以上)の場合、map/reduceを代わりに使ってください。 group注意: 現在のところ、shardの環境では、group()の代わりにmap/reduceを必ず使ってください。 group はグループ化されたアイテムを配列で返します。このコマンドはSQLのgroup byと非常によく似てます。SQLでは、 select a,b,sum(c) csum from coll where active=1 group by a,b これに対応するMongoDBは以下のようになります。 db.coll.group(
{key: { a:true, b:true },
cond: { active:1 },
reduce: function(obj,prev) { prev.csum += obj.c; },
initial: { csum: 0 }
});
注意: この結果は、一つのBSONオブジェクトとして返されるので、結果はなるべく小さくしてください(10,000キー以内)。大きすぎる場合例外が発生します。制限なしでの大きなグルーピングのためには、 map/reduce を使ってください。 group は、次のフィールドを含む1つのオブジェクトをパラメータとして渡します。
groupされたデータをソートするには、戻り値を単純にクライアントサイドでしてください。次の例は、 group() を使って、 count の実装の例です。 function gcount(collection, condition) {
var res =
db[collection].group(
{ key: {},
initial: {count: 0},
reduce: function(obj,prev){ prev.count++;},
cond: condition } );
// group() returns an array of grouped items. here, there will be a single
// item, as key is {}.
return res[0] ? res[0].count : 0;
}
例下記の例は、このようなデータを仮定しています。 { domain: "www.mongodb.org"
, invoked_at: {d:"2009-11-03", t:"17:14:05"}
, response_time: 0.05
, http_action: "GET /display/DOCS/Aggregation"
}
2009年11月の http_action の statを表示。 db.test.group(
{ cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
, key: {http_action: true}
, initial: {count: 0, total_time:0}
, reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
, finalize: function(out){ out.avg_time = out.total_time / out.count }
} );
[
{
"http_action" : "GET /display/DOCS/Aggregation",
"count" : 1,
"total_time" : 0.05,
"avg_time" : 0.05
}
]
2009年11月のそれぞれの日のそれぞれのドメインのstatを表示。 db.test.group(
{ cond: {"invoked_at.d": {$gt: "2009-11", $lt: "2009-12"}}
, key: {domain: true, invoked_at.d: true}
, initial: {count: 0, total_time:0}
, reduce: function(doc, out){ out.count++; out.total_time+=doc.response_time }
, finalize: function(out){ out.avg_time = out.total_time / out.count }
} );
[
{
"http_action" : "GET /display/DOCS/Aggregation",
"count" : 1,
"total_time" : 0.05,
"avg_time" : 0.05
}
]
groupを様々な言語で使ういくつかのドライバで、group helperファンクションを提供しています。 提供していないドライバでは、groupコマンドをdbコマンドに手動で直接発行することもできます。 Mongoシェルでの例です。 > db.foo.find()
{"_id" : ObjectId( "4a92af2db3d09cb83d985f6f") , "x" : 1}
{"_id" : ObjectId( "4a92af2fb3d09cb83d985f70") , "x" : 3}
{"_id" : ObjectId( "4a92afdab3d09cb83d985f71") , "x" : 3}
> db.$cmd.findOne({group:{ns:"foo",cond:{},key:{x:1},initial:{count:0},$reduce:function(obj,prev){prev.count++;}}})
{"retval" : [{"x" : 1 , "count" : 1},{"x" : 3 , "count" : 2}] , "count" : 3 , "keys" : 2 , "ok" : 1}
(key の代わりに) keyf を使う場合、 $を必ずプレフィクスとして付けてください。たとえば、 db.$cmd.findOne({group : {
... ns : "foo",
... $keyf : function(doc) { return {"x" : doc.x}; },
... initial : {count : 0},
... $reduce : function(obj,prev) { prev.count++; }}})
Map/ReduceMongoDBは、もっと複雑な集約なために MapReduce を提供しています。CouchDBユーザへ: MongoDBの基本的なクエリーはmap/reduceを使わないことに注意してください。 参照
|

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.
These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group. blog comments powered by Disqus