MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

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で日付を文字列に変換してからグループ化する方法も利用でき、より直感的に記述できる場合があります。用途や好みに応じて使い分けるとよいでしょう。

  1. MongoDB集計パイプラインで重複するNameフィールド値ごとの出現回数を取得する方法

    MongoDBでは、$unwindと$groupを組み合わせた集計(アグリゲーション)パイプラインを使うことで、配列内に存在する重複したフィールド値を名前ごとにグループ化し、それぞれの出現回数を簡単に取得できます。ここでは、具体的な例をもとにその手順を解説します。サンプルコレクションの作成まずは、ドキュメントを含むコレクションを作成してみましょう。以下の例では、demo558というコレクションに、国コードと複数人の受講科目情報を持つドキュメントを挿入します。> db.demo558.insertOne( ... { ... _id : 100, ... CountryCode

  2. MongoDBで生年月日を年齢に変換する方法

    MongoDBでは、集計パイプライン(aggregate)を活用することで、保存されている生年月日(DateOfBirth)のデータから現在の年齢を簡単に算出できます。この記事では、実際のコード例を使いながらその手順をわかりやすく解説します。1. コレクションにドキュメントを挿入するまずは、生年月日を含むドキュメントを持つコレクションを作成します。以下のように insertOne() メソッドを使用します。> db.demo754.insertOne({DateOfBirth:new Date(2000-05-03)}); { acknowledged : true, ins