HOWTO · MongoDB

MongoDB で 2つの日付の間のオブジェクトを検索する

この MongoDB レッスンでは、日付範囲でクエリを実行する方法、日付に基づいてクエリを返す方法、および MongoDB で 2つの日付を比較する方法を示します。 コマンド $gte、$lte、$gt、および $lt についても説明します。

このページの内容

MongoDB の日付範囲クエリでは、保存されている BSON Date フィールドと Date 値を比較します。ドキュメントで使われているフィールド名を指定し、UTC を意図する場合は範囲の境界も UTC で記述してください。

MongoDB で2つの日付の間にあるドキュメントを検索する

day フィールドが BSON Date として保存されている data コレクションなら、db.data.find({ day: { $gte: ISODate("2022-01-21T00:00:00Z"), $lt: ISODate("2022-01-24T00:00:00Z") } }) を使います。この範囲は開始時点を含み、終了時点を含まないため、UTC の1月21日から1月23日までが対象です。data と day は、実際のコレクション名と日付フィールド名に置き換えてください。

次の実行可能な例は、この日付範囲クエリを実行可能な形で示したものです。同じ day フィールドと、開始を含み終了を含まない同じ時点の範囲を使います。比較をローカルで模擬するもので、MongoDB には接続しません。

次の例を実行してください。

このセクションのコードと表示されるラベルや出力は英語のままです。

const records = [
  { day: new Date("2022-01-20T00:00:00Z"), amount: 40 },
  { day: new Date("2022-01-21T00:00:00Z"), amount: 32 },
  { day: new Date("2022-01-22T00:00:00Z"), amount: 19 },
  { day: new Date("2022-01-23T00:00:00Z"), amount: 29 },
  { day: new Date("2022-01-24T00:00:00Z"), amount: 35 },
];
const start = new Date("2022-01-21T00:00:00Z");
const end = new Date("2022-01-24T00:00:00Z");
const matches = records.filter(({ day }) => day >= start && day < end);
for (const { day, amount } of matches) {
  console.log(`${day.toISOString()} amount=${amount}`);
}
2022-01-21T00:00:00.000Z amount=32
2022-01-22T00:00:00.000Z amount=19
2022-01-23T00:00:00.000Z amount=29

日付範囲の境界を含めるか除外するかを選ぶ

MongoDB の比較演算子によって、境界値が検索結果に含まれるかどうかが決まります。$gt は「より大きい」、$lt は「より小さい」を表し、どちらも境界と完全に一致するドキュメントは含みません。$gte は「以上」、$lte は「以下」を表し、どちらも境界との一致を含みます。一般的な「開始を含み、終了を含まない」範囲には、$gte と $lt を組み合わせます。両端の時点に完全一致する値も含める場合は、$gte と $lte を使います。

境界は暦日の名前だけでなく、具体的な時点として選びます。UTC の1日全体を対象にするなら、その日の午前0時を開始、翌日の午前0時を終了とする、終了時点を含まないクエリを使えます。これにより、その日の最後のミリ秒を推測せずに済みます。

指定した日付より後または前のドキュメントを検索する

ある時点より後のドキュメントを検索するには、db.data.find({ day: { $gt: ISODate("2022-01-22T00:00:00Z") } }) を使います。この条件では、その時点と完全に一致するドキュメントは除外されます。一致するドキュメントも含めるには $gte を使います。ある時点より前のドキュメントを検索するには、db.data.find({ day: { $lt: ISODate("2022-01-22T00:00:00Z") } }) を使います。その時点自体も含めるには $lte を使います。片側だけを指定するクエリでは、日付フィールドの条件内に比較演算子を1つだけ指定します。

日付値とタイムスタンプ値を比較する

BSON Date はミリ秒精度の UTC 時点を保存するため、タイムスタンプにも同じ範囲指定のパターンを使えます。たとえば、到着時刻のフィールドは db.flights.find({ PassengerArrivalTime: { $gte: ISODate("2018-05-19T11:10:23Z"), $lt: ISODate("2018-08-25T16:40:12Z") } }) で検索できます。指定した文字列が UTC を表す場合は Z を付けます。元の時刻が別のタイムゾーンで表されている場合は、境界値として使う前に正しい UTC 時点へ変換してください。

BSON Date の型とタイムゾーンを確認する

フィールドには "2022-01-21" のような文字列ではなく、BSON Date を保存してください。日付の比較演算子は通常、互換性のある BSON 型の値を比較します。日付を表す文字列は Date 値の代わりにはなりません。mongosh では ISODate("2022-01-21T00:00:00Z") を使って、クエリ用の Date 値を作成できます。アプリケーションコードでは、明確に定義された時点からドライバーの Date 型を作り、Date パラメーターとして渡してください。

日付だけの値では、タイムゾーンを決めるまで普遍的な時点を特定できません。対象の暦日を UTC とローカルタイムゾーンのどちらで扱うかを決め、範囲の両端を一貫した方法で変換します。ローカルの暦日を対象にする場合は、そのタイムゾーンの規則に従って翌日のローカル午前0時を計算し、それぞれの境界を UTC に変換してください。ローカルの1日の経過時間が毎回同じとは限りません。クエリで予想外にレコードが除外される場合は、保存されている BSON 型、フィールド名、両端の UTC 時点を確認してください。