MongoDB / Mongooseは特定の日付でクエリを実行していますか?


141

特定の日付を照会することは可能ですか?

mongoクックブックで、日付範囲のクエリを実行することができることがわかりました 、次のような:

db.posts.find({"created_on": {"$gte": start, "$lt": end}})

しかし、それは特定の日付で可能ですか?これは動作しません:

db.posts.find({"created_on": new Date(2012, 7, 14) })

回答:


211

これは、DBに保存した日付に時間がない場合(年、月、日のみ)に機能します。

保存した日付がnew Date()である可能性があります。これには、時間コンポーネントが含まれます。これらの時間をクエリするには、1日のすべての瞬間を含む日付範囲を作成する必要があります。

db.posts.find( //query today up to tonight
  {"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})

29
Date()関数では、月の引数は1ではなく0から始まることに
注意して

次の日付を取得するために、両方をハードコードするよりも1日行うほうがよいのではないですか?
raju

2
日付が次のように保存されている場合、このメソッドは正常に機能しますか:>> "date":ISODate( "2016-01-04T14:07:17.496Z")
santhosh

月と日付の切り替えはありませんか。日付の形式は、yyyy、dd、MM
thethakuri

123

... 5年以上後、代わりにdate-fnsを使用することを強くお勧めします

import endOfDayfrom 'date-fns/endOfDay'
import startOfDay from 'date-fns/startOfDay'

MyModel.find({
  createdAt: {
    $gte: startOfDay(new Date()),
    $lte: endOfDay(new Date())
  }
})

Moment.jsを使用しているユーザー向け

const moment = require('moment')

const today = moment().startOf('day')

MyModel.find({
  createdAt: {
    $gte: today.toDate(),
    $lte: moment(today).endOf('day').toDate()
  }
})

重要:すべての瞬間は変更可能です!

tomorrow = today.add(1, 'days')それも変異するので機能しませんtoday。呼び出しはmoment(today)、暗黙的に複製することでその問題を解決します today


13
.startOf('day').hours(0).minutes(0).seconds(0)の代わりに使用することをお勧めします。最初の行は次のようになりますので:var today = moment().startOf('day')
ジムGeurts

2
私たちが使用している場合はmoment(today)、オブジェクトのクローンを作成するために、別の解決策は以下のとおりです。var tomorrow = today.clone().add(1, 'days')
johntellsall

1
@johntellsall暗黙の複製ではなく、明示的な複製。同じ結果ですが、おそらく実際には読みやすくなります。
Pier-Luc Gendreau、2017年

1
または、次のことを提案することもでき$ltますmoment(today).endOf('day')。翌日以降の実績が含まれないようにするため。
グレドゥアン2018年

1
私のために moment(today).endOf('day')は次の時間と同じ日を与えます:23:59:59.999。したがって、実際にはを使用する方がより正確に見えます$lte。そうでない場合、その特定の時間のオブジェクトは無視されます。
leonprou

11

ええ、Dateオブジェクトは日付と時刻を補正するので、日付値だけと比較しても機能しません。

$ where演算子を使用するだけで、JavaScriptのブール式でより複雑な条件を表現できます:)

db.posts.find({ '$where': 'this.created_on.toJSON().slice(0, 10) == "2012-07-14"' })

created_on 日時フィールドであり、 2012-07-14あり、指定された日付です。

日付は正確にYYYY-MM-DD形式でなければなりません。

注:使用は$where控えめにしてください。パフォーマンスに影響します。


10

やってみました:

db.posts.find({"created_on": {"$gte": new Date(2012, 7, 14), "$lt": new Date(2012, 7, 15)}})

遭遇する問題は、Mongoで日付がタイムスタンプとして保存されることです。つまり、日付を一致させるには、タイムスタンプを一致させる必要があります。あなたの場合、私はあなたが日と一致しようとしていると思います(すなわち、特定の日の00:00から23:59まで)。日付が時間なしで保存されている場合は、問題ありません。それ以外の場合、gteが機能しない場合は、同じ日の時間の範囲として日付を指定してみてください(つまり、start = 00:00、end = 23:59)。

同様の質問


1
これには、指定された日付よりも新しいすべての要素が含まれます。これは、おそらくOPが望んでいたことではありません。他の回答のように「lt」オプションを追加することを検討してください。
BenSower、2016年

$gte代わりに持ってgteいる方がいいと思います。
ジャックブランク

これはすでに上記でより正確に回答されていますが、私の回答がオフであることを知っていることは私を悩ませていたので、質問に対して正しいように更新しました。ねえ、それは4年になります。笑
マイケルDジョンソン

6

APIメソッドに次のアプローチを使用して、特定の日の結果を取得できます。

# [HTTP GET]
getMeals: (req, res) ->
  options = {}
  # eg. api/v1/meals?date=Tue+Jan+13+2015+00%3A00%3A00+GMT%2B0100+(CET)
  if req.query.date?
    date = new Date req.query.date
    date.setHours 0, 0, 0, 0
    endDate = new Date date
    endDate.setHours 23, 59, 59, 59
    options.date =
      $lt: endDate
      $gte: date

  Meal.find options, (err, meals) ->
      if err or not meals
        handleError err, meals, res
      else
        res.json createJSON meals, null, 'meals'

1

データベースの重複データに関連する問題がありました。日付フィールドには1であるはずの複数の値があり、参照のために問題を解決する方法を追加したいと思いました。

数値の「値」フィールドと日付の「日付」フィールドを持つ「データ」と呼ばれるコレクションがあります。べき等であると考えていたプロセスがありましたが、2回目の実行で1日あたり2 x値が追加されました。

{ "_id" : "1", "type":"x", "value":1.23, date : ISODate("2013-05-21T08:00:00Z")}
{ "_id" : "2", "type":"x", "value":1.23, date : ISODate("2013-05-21T17:00:00Z")}

2つのレコードのうち1つだけが必要なので、dbをクリーンアップするためにJavaScriptを使用する必要がありました。私たちの最初のアプローチは、結果を反復処理し、午前6時から午前11時までの時間にすべてのフィールドを削除することでした(すべての重複は午前中にありました)が、実装中に変更を加えました。これを修正するために使用されるスクリプトは次のとおりです。

var data = db.data.find({"type" : "x"})
var found = [];
while (data.hasNext()){
    var datum = data.next();
    var rdate = datum.date;
    // instead of the next set of conditions, we could have just used rdate.getHour() and checked if it was in the morning, but this approach was slightly better...
    if (typeof found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] !== "undefined") {
       if (datum.value != found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()]) {
           print("DISCREPENCY!!!: " + datum._id + " for date " + datum.date);
       }
       else {
           print("Removing " + datum._id);
           db.data.remove({ "_id": datum._id});
       }
    }
    else {
       found[rdate.getDate()+"-"+rdate.getMonth() + "-" + rdate.getFullYear()] = datum.value;
    }
}

そしてそれを実行しました mongo thedatabase fixer_script.js

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.