MongoDBで2つの日付間のフィールドをカウント・合計する方法($gte・$lte・$sumの使い方)
MongoDBで2つの日付の間に該当するドキュメントの件数を数えたり、数値フィールドの合計を求めたりするには、集計フレームワーク(Aggregation Pipeline)を使用するのが最も効率的です。$matchステージで比較演算子の $gte(以上)と $lte(以下)により日付範囲を絞り込み、続く $group ステージの $sum 演算子で合計値とカウントを同時に算出できます。
サンプルコレクションの作成
まずは、insertOne() メソッドでテストデータを登録するところから始めましょう。
> db.countandsumdemo.insertOne({"Value":10,"created_at":ISODate('2019-10-11')});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e038e6df5e889d7a51994fa")
}
> db.countandsumdemo.insertOne({"Value":50,"created_at":ISODate('2019-01-31')});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e038e77f5e889d7a51994fb")
}
> db.countandsumdemo.insertOne({"Value":100,"created_at":ISODate('2019-06-31')});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e038e8af5e889d7a51994fc")
}登録されたドキュメントの確認
find() メソッドを使うと、コレクション内のすべてのドキュメントを表示できます。
> db.countandsumdemo.find().pretty();
実行結果は次のとおりです。
{
"_id" : ObjectId("5e038e6df5e889d7a51994fa"),
"Value" : 10,
"created_at" : ISODate("2019-10-11T00:00:00Z")
}
{
"_id" : ObjectId("5e038e77f5e889d7a51994fb"),
"Value" : 50,
"created_at" : ISODate("2019-01-31T00:00:00Z")
}
{
"_id" : ObjectId("5e038e8af5e889d7a51994fc"),
"Value" : 100,
"created_at" : ISODate("2019-07-01T00:00:00Z")
}ポイント: 3つ目のドキュメントには「2019-06-31」を指定しましたが、保存結果は「2019-07-01」になっています。6月は30日までしか存在しないため、存在しない日付を指定すると自動的に翌日へ繰り上げられるのです。実務では日付入力のミスに注意しましょう。
2つの日付間でカウントと合計を求めるクエリ
ここからが本題です。次のクエリでは、「2019-05-01」から「2019-12-31」の間に作成されたドキュメントを対象に、Value フィールドの合計(SUM)と件数(COUNT)を一度に取得しています。
> db.countandsumdemo.aggregate(
...  [{
... $match: {
... created_at: {
... $gte: new Date('2019-05-01'),
... $lte: new Date('2019-12-31')
... }
... }
... }, {
... $group: {
... _id: null,
... SUM: {
... $sum: "$Value"
... },
... COUNT: {
... $sum: 1
... }
... }
...  }]
... );実行結果は次のとおりです。
{ "_id" : null, "SUM" : 110, "COUNT" : 2 }クエリのポイント解説
- $match: created_at が 2019-05-01 以上・2019-12-31 以下のドキュメントのみを抽出します。created_at にインデックスを設定しておけば、この段階で効率的に絞り込めます。
- $group: _id: null を指定すると、条件に一致したすべてのドキュメントが1つのグループにまとめられます。
- SUM: { $sum: "$Value" }: 各ドキュメントの Value フィールドの値を足し合わせて合計を算出します。
- COUNT: { $sum: 1 }: ドキュメント1件につき1を加算するため、条件に一致した件数を数えられます。
今回の例では、日付範囲に一致したのは「2019-07-01」(Value: 100)と「2019-10-11」(Value: 10)の2件であるため、合計は 110、件数は 2 となります。「2019-01-31」のドキュメントは範囲外のため対象外です。このように $match と $group を組み合わせれば、複雑な集計処理も1つのパイプラインでシンプルかつ高速に実現できます。
-
MongoDBのNumberLong(x)とNumberLong("x")の違いとは?
MongoDBにおけるNumberLong(x)とNumberLong(x)の違いとは?MongoDBで64ビット整数を扱う際に使われるNumberLongですが、引数の渡し方によって挙動が大きく異なります。数値をそのまま渡すNumberLong(x)の場合、値が精度の限界を超えると丸め処理が行われてしまうのに対し、文字列として渡すNumberLong(x)では丸められることなく正確な値が保持されます。この現象の原因は、シェル上の数値リテラルが倍精度浮動小数点数(double)として解釈されることにあります。988998985857575789のような非常に大きな整数は、double型では正確
-
MongoDBでカーソルの反復回数をカウントする方法を解説
MongoDBでカーソルの反復をカウントするには?MongoDBにおいて、whileループとfind()メソッドが返すカーソルを組み合わせた独自のロジックを実装することで、カーソルの反復回数(特定の条件に一致するドキュメント数)をカウントできます。本記事では、実際のコード例を通じて、その具体的な手順をわかりやすく解説します。1. ドキュメントを含むコレクションを作成するまず、サンプル用のドキュメントを挿入してコレクションを作成します。> db.demo724.insertOne( ... { ... details: ... { ...