$dateAdd(集計)
定義
$dateAdd
バージョン 5.0 で追加
指定された時間単位数の分だけ
Date()
オブジェクトを増加させます。$dateAdd
式の構文は次のとおりです。{ $dateAdd: { startDate: <Expression>, unit: <Expression>, amount: <Expression>, timezone: <tzExpression> } } Date()
を返します。startDate
は、Date 型、Timestamp 型、または ObjectId 型に変換される任意の式にできます。どのデータ型が入力に使用されるかにかかわらず、返される値はDate()
オブジェクトになります。フィールド必須/オプション説明startDate
必須unit
必須unit
は、startDate
に追加された時間のamount
を測定するために使用されます。unit
は、次のいずれかの文字列に変換される式です。year
quarter
week
month
day
hour
minute
second
millisecond
amount
必須startDate
に追加されたunits
の数。amount
は、integer または long に変換される式です。amount
は、その値が精度を失うことなく long に変換できる場合は、integer decimal または double に変換することもできます。timezone
任意操作を実行するタイムゾーン。
<tzExpression>
は、 Olson タイムゾーン識別子 として形式された string に変換される有効な 式 である必要があります。 または UTC オフセット 。timezone
が指定されていない場合、結果はUTC
に表示されます。形式例Olson タイムゾーン識別子"America/New_York" "Europe/London" "GMT" UTC オフセット+/-[hh]:[mm], e.g. "+04:45" +/-[hh][mm], e.g. "-0530" +/-[hh], e.g. "+03" 式と型の詳細については、「式演算子と「BSON types」を参照してください。
動作
時間測定
MongoDB は一般的なデータベースの使用法に従い、UTC の時間で動作します。dateAdd
式は常に UTC のstartDate
を受け取り、UTC で結果を返します。 timezone
が指定されている場合は、指定されたtimezone
を使用して計算が行われます。 計算に夏時間 (DST) が含まれる場合、タイムゾーンは特に重要です。
unit
が month
またはそれより大きい場合、操作は月の最終日を考慮して調整されます。たとえば、10 月の最終日に month
を 1 つ足すと、「月末日」の調整が行われます。
{ $dateAdd: { startDate: ISODate("2020-10-31T12:10:05Z"), unit: "month", amount: 1 } }
11 月は 10 月よりも日数が少ないため、返される日付 ISODate("2020-11-30T12:10:05Z")
は 31 日ではなく 30 日であることに注意してください。
タイムゾーン
<timezone>
フィールドで Olson タイムゾーン識別子を使用する際、指定されたタイムゾーンに該当する場合、MongoDB は DST オフセットを適用します。
たとえば、次のドキュメントを含む sales
コレクションを考えます。
{ "_id" : 1, "item" : "abc", "price" : 20, "quantity" : 5, "date" : ISODate("2017-05-20T10:24:51.303Z") }
次の集計は、MongoDB がタイムゾーン識別子の DST オフセットを取り扱う方法を示しています。この例では、$hour
演算子と $minute
演算子を使用して、date
フィールドの対応する部分を返します。
db.sales.aggregate([ { $project: { "nycHour": { $hour: { date: "$date", timezone: "-05:00" } }, "nycMinute": { $minute: { date: "$date", timezone: "-05:00" } }, "gmtHour": { $hour: { date: "$date", timezone: "GMT" } }, "gmtMinute": { $minute: { date: "$date", timezone: "GMT" } }, "nycOlsonHour": { $hour: { date: "$date", timezone: "America/New_York" } }, "nycOlsonMinute": { $minute: { date: "$date", timezone: "America/New_York" } } } }])
この操作では、次の結果を返します。
{ "_id": 1, "nycHour" : 5, "nycMinute" : 24, "gmtHour" : 10, "gmtMinute" : 24, "nycOlsonHour" : 6, "nycOlsonMinute" : 24 }
例
将来の日付を追加する
これらのドキュメントを含むカスタマーの注文のコレクションについて考えてみます。
db.shipping.insertMany( [ { custId: 456, purchaseDate: ISODate("2020-12-31") }, { custId: 457, purchaseDate: ISODate("2021-02-28") }, { custId: 458, purchaseDate: ISODate("2021-02-26") } ] )
通常の発送期間は 3 日です。集計パイプラインで $dateAdd
を使用して、expectedDeliveryDate
を 3 日後に設定できます。
db.shipping.aggregate( [ { $project: { expectedDeliveryDate: { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 3 } } } }, { $merge: "shipping" } ] )
$project
ステージで $dateAdd
を使用してpurchaseDate
に 3 日を追加した後、 $merge
ステージで expectedDeliveryDate
により元のドキュメントをアップデートします。
結果のドキュメントは次のようになります。
{ "_id" : ObjectId("603dd4b2044b995ad331c0b2"), "custId" : 456, "purchaseDate" : ISODate("2020-12-31T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-01-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b3"), "custId" : 457, "purchaseDate" : ISODate("2021-02-28T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-03T00:00:00Z") } { "_id" : ObjectId("603dd4b2044b995ad331c0b4"), "custId" : 458, "purchaseDate" : ISODate("2021-02-26T00:00:00Z"), "expectedDeliveryDate" : ISODate("2021-03-01T00:00:00Z") }
日付範囲でフィルタリングする
このコードで前回の例の shipping
コレクションを更新し、次のドキュメントに配送日を追加します。
db.shipping.updateOne( { custId: 456 }, { $set: { deliveryDate: ISODate( "2021-01-10" ) } } ) db.shipping.updateOne( { custId: 457 }, { $set: { deliveryDate: ISODate( "2021-03-01" ) } } ) db.shipping.updateOne( { custId: 458 }, { $set: { deliveryDate: ISODate( "2021-03-02" ) } } )
出荷遅延を見つけます。$match
ステージで $dateAdd
を使用して、開始点( $purchaseDate
)と $dateAdd
で指定された期間によって定義された日付の範囲内のドキュメントに一致するフィルターを作成します。
db.shipping.aggregate( [ { $match: { $expr: { $gt: [ "$deliveryDate", { $dateAdd: { startDate: "$purchaseDate", unit: "day", amount: 5 } } ] } } }, { $project: { _id: 0, custId: 1, purchased: { $dateToString: { format: "%Y-%m-%d", date: "$purchaseDate" } }, delivery: { $dateToString: { format: "%Y-%m-%d", date: "$deliveryDate" } } } } ] )
$match
ステージでは、$gt
と $dateAdd
を式($expr
)で使用して、実際の deliveryDate
と予想される日付を比較します。purchaseDate
から配達日が 5 日以上経過したドキュメントは、$project
ステージに渡されます。
$project
ステージでは、 $dateToString
式を使用して日付をより読みやすい形式に変換します。 変換を行わない場合、MongoDB は日付をISODate形式で返し、UTC タイムゾーンを想定します。
この例では、1 つのレコードのみが返されます。
{ "custId" : 456, "purchased" : "2020-12-31", "delivery" : "2021-01-10" }
夏時間に合わせて調整する
すべての日付は、内部的には UTC 時間でストアされます。timezone
が指定されている場合、$dateAdd
はローカル タイムを使用して計算を実行します。結果は UTC で表示されます。
複数のタイムゾーンのカスタマーがいて、day
や hour
で請求した場合、夏時間が請求期間にどのような影響を与えるかを確認したい場合があります。
この接続時間のコレクションを作成します。
db.billing.insertMany( [ { location: "America/New_York", login: ISODate("2021-03-13T10:00:00-0500"), logout: ISODate("2021-03-14T18:00:00-0500") }, { location: "America/Mexico_City", login: ISODate("2021-03-13T10:00:00-00:00"), logout: ISODate("2021-03-14T08:00:00-0500") } ] )
まず各ドキュメントの login
日付に 1 日を追加し、次に 24 時間を追加します。
db.billing.aggregate( [ { $project: { _id: 0, location: 1, start: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login" } }, days: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } } } }, hours: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } } } }, startTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$login", timezone: "$location" } }, daysTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "day", amount: 1, timezone: "$location" } }, timezone: "$location" } }, hoursTZInfo: { $dateToString: { format: "%Y-%m-%d %H:%M", date: { $dateAdd: { startDate: "$login", unit: "hour", amount: 24, timezone: "$location" } }, timezone: "$location" } }, } } ] ).pretty()
$dateToString
式は、読みやすいように出力を再フォーマットします。 結果の概要は次のとおりです。
フィールド | New York | メキシコシティ |
---|---|---|
始める | 2021-03-13 15:00 | 2021-03-13 10:00 |
スタート、タイムゾーン情報 | 2021-03-13 10:00 | 2021-03-13 04:00 |
1 日 | 2021-03-14 14:00 | 2021-03-14 10:00 |
1 日、タイムゾーン情報 | 2021-03-14 10:00 | 2021-03-14 04:00 |
24 時間 | 2021-03-14 15:00 | 2021-03-14 10:00 |
24 時間、タイムゾーン情報 | 2021-03-14 11:00 | 2021-03-14 04:00 |
このチャートには、いくつかの重要なポイントがあります。
書式設定されていない日付は UTC で返されます。ニューヨークの
$login
は UTC -5 ですが、start
行、days
行、およびhours
行には時刻が UTC で表示されます。3 月 14 日はニューヨークでは夏時間の開始日ですが、メキシコでは違います。計算された時間は、ロケーションが DST に切り替わり、ある
day
から次の日に移るときに調整されます。DST は、
hour
ではなく、day
の長さを変更します。hours
では、DST の変更はありません。DST の調整は、測定unit
がday
以上で、計算が指定されたtimezone
で時差が生じる場合にのみ行われます。