MongoDBで日付ごとにグループ化!重複する日付レコードの件数をカウントする方法
MongoDBで日付ごとにグループ化して重複レコードをカウントする方法
MongoDBで「同じ日付のデータが何件あるか」を調べたい場合には、集計フレームワークのaggregate()メソッドと$groupステージを組み合わせます。この記事では、サンプルコレクションを作成し、日付単位でレコードをグループ化して出現回数をカウントするまでの一連の手順を、実際のクエリと実行結果とあわせて解説します。
サンプルコレクションの作成とドキュメントの挿入
まず、動作確認用のコレクションを作成します。insertOne()メソッドを使い、DueDateフィールドに日付を持つドキュメントを複数件登録しましょう。
> db.demo160.insertOne({"DueDate":new ISODate()});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e357525fdf09dd6d0853a04")
}
> db.demo160.insertOne({"DueDate":new ISODate("2019-01-11")});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e357532fdf09dd6d0853a05")
}
> db.demo160.insertOne({"DueDate":new ISODate()});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e357534fdf09dd6d0853a06")
}
> db.demo160.insertOne({"DueDate":new ISODate("2019-01-11")});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e357538fdf09dd6d0853a07")
}
> db.demo160.insertOne({"DueDate":new ISODate("2020-04-10")});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e357542fdf09dd6d0853a08")
}挿入したドキュメントの確認
find()メソッドを引数なしで実行すると、コレクション内のすべてのドキュメントを取得できます。
> db.demo160.find();
このクエリを実行すると、次のような出力が得られます。
{ "_id" : ObjectId("5e357525fdf09dd6d0853a04"), "DueDate" : ISODate("2020-02-01T12:55:01.983Z") }
{ "_id" : ObjectId("5e357532fdf09dd6d0853a05"), "DueDate" : ISODate("2019-01-11T00:00:00Z") }
{ "_id" : ObjectId("5e357534fdf09dd6d0853a06"), "DueDate" : ISODate("2020-02-01T12:55:16.787Z") }
{ "_id" : ObjectId("5e357538fdf09dd6d0853a07"), "DueDate" : ISODate("2019-01-11T00:00:00Z") }
{ "_id" : ObjectId("5e357542fdf09dd6d0853a08"), "DueDate" : ISODate("2020-04-10T00:00:00Z") }この時点で、「2020-02-01」と「2019-01-11」のデータがそれぞれ2件ずつ存在していることが分かります。
日付ごとにグループ化してカウントするクエリ
続いて、本題となる日付単位のグループ化クエリです。$groupステージの中で$dayOfYear(年内の通算日)と$year(年)を組み合わせたキーを生成することで、同じ年・同じ日のレコードを1つのグループにまとめています。
> db.demo160.aggregate([
... { $group: {
... _id: {
... $add: [
... { $dayOfYear: "$DueDate"},
... { $multiply:
... [400, {$year: "$DueDate"}]
... }
... ]},
... Frequency: { $sum: 1 },
... d: {$min: "$DueDate"}
... }
... },
... { $sort: {_id: 1} },
... { $limit: 100},
... { $project: { date: "$d", Frequency: 1, _id: 0} }
... ]);パイプラインの各要素の役割は以下の通りです。
- _id:「年×400+年内通算日」で一意な日付キーを生成します。400は1年の最大日数(366日)より大きいため、異なる年の同じ日が同じキーになることはありません。
- Frequency:
$sum: 1によってグループ内のレコード件数、つまりその日の出現回数をカウントします。 - d:
$minでグループ内の最小日付を取得し、代表日付として保持します。
その後、$sortで並べ替え、$limitで最大100件に制限し、$projectで出力に不要なフィールドを除外しています。
実行結果
上記のパイプラインを実行すると、日付ごとの出現回数が次のように取得できます。
{ "Frequency" : 2, "date" : ISODate("2019-01-11T00:00:00Z") }
{ "Frequency" : 2, "date" : ISODate("2020-02-01T12:55:01.983Z") }
{ "Frequency" : 1, "date" : ISODate("2020-04-10T00:00:00Z") }結果から、2019-01-11が2件、2020-02-01が2件、2020-04-10が1件となっており、重複する日付レコードが正しくカウントされていることが確認できます。
まとめ
MongoDBで日付の重複を集計する際は、$groupと日付演算子($dayOfYearや$yearなど)を組み合わせるのが基本のアプローチです。なお、MongoDB 4.0以降では$dateToStringで日付を文字列に変換してからグループ化する方法も利用でき、より直感的に記述できる場合があります。用途や好みに応じて使い分けるとよいでしょう。
-
MongoDB集計パイプラインで重複するNameフィールド値ごとの出現回数を取得する方法
MongoDBでは、$unwindと$groupを組み合わせた集計(アグリゲーション)パイプラインを使うことで、配列内に存在する重複したフィールド値を名前ごとにグループ化し、それぞれの出現回数を簡単に取得できます。ここでは、具体的な例をもとにその手順を解説します。サンプルコレクションの作成まずは、ドキュメントを含むコレクションを作成してみましょう。以下の例では、demo558というコレクションに、国コードと複数人の受講科目情報を持つドキュメントを挿入します。> db.demo558.insertOne( ... { ... _id : 100, ... CountryCode
-
MongoDBで生年月日を年齢に変換する方法
MongoDBでは、集計パイプライン(aggregate)を活用することで、保存されている生年月日(DateOfBirth)のデータから現在の年齢を簡単に算出できます。この記事では、実際のコード例を使いながらその手順をわかりやすく解説します。1. コレクションにドキュメントを挿入するまずは、生年月日を含むドキュメントを持つコレクションを作成します。以下のように insertOne() メソッドを使用します。> db.demo754.insertOne({DateOfBirth:new Date(2000-05-03)}); { acknowledged : true, ins