2017-04-02 12 views
7

私のプロジェクトでmongoDB c#latest driverすなわち3. +を使用しています。私はdaterangepickerを使って、Today、Last Day、Yesterday、This Monthなどの異なる日付フィルタ基準を持っています。ここでmongoDBのC#ドライバを使用して日付のみでフィルタリングする

は私のモデルであり、ここで

public class Student 
    { 
     public Student() 
     { 
     } 
     [BsonId] 
     [BsonRepresentation(BsonType.ObjectId)] 
     public string Id { get; set; } 
     [BsonDateTimeOptions(Kind = DateTimeKind.Local)] 
     public DateTime CreatedOn { get; set; } 
     [BsonDateTimeOptions(Kind = DateTimeKind.Local)] 
     public DateTime ModifiedOn { get; set; } 
     public string Name { get; set; } 
     public string Description { get; set; } 
    } 

は、ドライバのコード

var server = new MongoClient(_connectionString); 
var db = server.GetDatabase("Students"); 
var collection = db.GetCollection<Student>("student"); 
var filterBuilder = Builders<Student>.Filter; 
var start = new DateTime(2017, 03, 29); 
var end = new DateTime(2017, 03, 31); 
var filter = filterBuilder.Gte(x => x.CreatedOn, new BsonDateTime(start)) & 
      filterBuilder.Lte(x => x.CreatedOn, new BsonDateTime(end)); 
List<Student> searchResult = collection.Find(filter).ToList(); 

は、このコードは正常に動作しますが、私は今日、フィルタを選択すると、日付がそれはdidnの

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 03, 31); 

なっています現在の日のレコードを返します。時間も計算しています。

私はDateTime.Nowとして日付を保存しています。私が照会しているサンプルISO日付は

"CreatedOn": ISODate("2017-03-31T20:27:12.914+05:00"), 
"ModifiedOn": ISODate("2017-03-31T20:27:12.914+05:00"), 

これは私が使用しているフィルタの日付です。私は終了日から-1を引く必要がありますか? enter image description here

私が間違っていることを助けてください。

+0

はあなたが返すように現在の日のためのクエリを期待しているあなたのコレクションからのサンプル文書を追加することはできますか? – Veeram

+0

私はDateTime.Nowをデータベースに保存しています。私の編集した質問を参照してください。 –

+0

今日の例のThanls @Veeram私はAddDaysメソッドを使うことができますが、他の方法については、何らかの汎用ソリューションが必要です。 –

答えて

-1

あなたは

new DateTime(2017, 03, 31); 

を使用するときに、それはまた、時間を計算する意味、DateTimeオブジェクトを取得します。 だから、両方の開始と停止のための同じ構文解析を使用することによって、あなたが実際に等しい何かを得る:

var start = var end = new DateTime("31/03/2017 00:00:00.00"); 

確かに、あなたはおそらく、この特定の時間枠の下に何のレコードを持っていません。 あなたが本当にすべて今日のレコードを取得したい場合は、あなたがそのような何か行う必要があります。

var start = new DateTime("31/03/2017 00:00:00.00"); 
var end = new DateTime("31/03/2017 23:59:59.99"); 
+0

文字列引数を取るオーバーロードはありません。 –

+0

@GhazanfarKhan彼はあなたを助けるためにここにいます。彼が間違っているならば、ただ彼に知らせてください。そのような言語を使用する必要はありません。あなたが理解したいと思っています。 – Sachin

+0

それを得ましたが、私はこれを期待していませんでした。 –

2

を私は特にインクルードの一部をオフセットしますが、タイムゾーンで混乱していると信じています。

MongoDbは常にUTC時刻で日付を保存します。

MongoDBの日付時刻を見ると、あなたのローカルタイムゾーンからのオフセットを常に考慮する必要があります。

あなたは常にローカルタイムゾーンで日付を送信します。 Mongo C#ドライバは、持続する前にローカルからUTCに時間を変更します。例えば

あなたがあるUTCからのオフセット何かISODate("2017-04-05T20:21:23.234Z")すなわちローカルタイムが表示されますDB内のドキュメントを見たとき、私はCreatedOn = 2017-04-05 15:21:23.234(ローカルタイムゾーン(アメリカ/シカゴ))が、 で文書を保存します-5時間。

[BsonDateTimeOptions(Kind = DateTimeKind.Local)]は、BSONをPOCOに戻すときにUTCから現地時間に変換するようにドライバに指示します。

ここで動作を説明するテストケースです。

コード:

class Program 
{ 

    static void Main(string[] args) 
    { 
     var mongo = new MongoClient("mongodb://localhost:27017/test"); 
     var db = mongo.GetDatabase("test"); 

     db.DropCollection("students"); 
     db.CreateCollection("students"); 

     var collection = db.GetCollection<Student>("students"); 

     var today = DateTime.Now; //2017-04-05 15:21:23.234 
     var yesterday = today.AddDays(-1);//2017-04-04 15:21:23.234 

     // Create 2 documents (yesterday & today) 
     collection.InsertMany(new[] 
      { 
      new Student{Description = "today", CreatedOn = today}, 
      new Student{Description = "yesterday", CreatedOn = yesterday}, 
      } 
     ); 

     var filterBuilder1 = Builders<Student>.Filter; 
     var filter1 = filterBuilder1.Eq(x => x.CreatedOn, today); 
     List<Student> searchResult1 = collection.Find(filter1).ToList(); 

     Console.Write(searchResult1.Count == 1); 

     var filterBuilder2 = Builders<Student>.Filter; 
     var filter2 = filterBuilder2.Eq(x => x.CreatedOn, yesterday); 
     List<Student> searchResult2 = collection.Find(filter2).ToList(); 

     Console.Write(searchResult2.Count == 1); 

    } 
} 

public class Student 
{ 
    [BsonId] 
    [BsonRepresentation(BsonType.ObjectId)] 
    public string Id { get; set; } 
    [BsonDateTimeOptions(Kind = DateTimeKind.Local)] 
    public DateTime CreatedOn { get; set; } 
    public string Description { get; set; } 
} 

コレクション:(モンゴシェルを通して見た)

{ 
     "_id" : ObjectId("58e559c76d3a9d2cb0449d84"), 
     "CreatedOn" : ISODate("2017-04-04T20:21:23.234Z"), 
     "Description" : "yesterday" 
} 
{ 
     "_id" : ObjectId("58e559c76d3a9d2cb0449d85"), 
     "CreatedOn" : ISODate("2017-04-05T20:21:23.234Z"), 
     "Description" : "today" 
} 

更新:

"CreatedOn": ISODate("2017-03-31T20:27:12.914+05:00") 

あなたの比較が働いていない理由は

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 03, 31); 

これはISODate("2017-03-31T00:00:00.000+05:00")よりISODate("2017-03-31T00:00:00.000+05:00")より$gte$lteなどとしてサーバーに送信取得し、それが上記のエントリを見つけるdoesntのです。

today日付を照会する正しい方法は

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 04, 01); 

ことと

var filter = filterBuilder.Gte(x => x.CreatedOn, start) & 
     filterBuilder.Lt(x => x.CreatedOn, end); 

にあなたのフィルタを更新しますだから今、あなたの範囲のクエリがISODate("2017-04-01T00:00:00.000+05:00")よりISODate("2017-03-31T00:00:00.000+05:00")より$gte$ltとしてサーバーに送信されますあなたは今日のすべての試合を見つけることができるはずです。

アップデート2

変更00:00:00に時間部分を設定した日時を格納するためのデータベースを。これによりdbからの方程式の時間部分が削除され、古い範囲のクエリはすべての場合にうまく機能します。

は、あなたの保存方法は、あなたが戻って古いフィルタ定義に行くことができます

​​

を使用するように変更します

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 03, 31); 

ような何かと

var filter = filterBuilder.Gte(x => x.CreatedOn, start) & 
     filterBuilder.Lte(x => x.CreatedOn, end); 

にあなたのフィルタを更新だから今、あなたの範囲のクエリがISODate("2017-03-31T00:00:00.000+05:00")よりISODate("2017-03-31T00:00:00.000+05:00")より$gte$lteとしてサーバーに送信され、あなたはすべてを見つけることができるはずです今日は一致します。

更新3 - 日付のみの比較BsonDocumentを使用しています。

ここでの考え方は、サーバーのUTC日付へ+5:00をあるタイムゾーンのオフセットを追加し、同じフォーマットで入力された文字列の日付の比較が続く$dateToSting演算子を使用して文字列yyyy-MM-dd形式に計算された日時を変換することです。

これはあなたのタイムゾーンでは機能しますが、はDSTのタイムゾーンを監視するには機能しません。

モンゴバージョン3.4

あなたは比較の後、最終的な応答からCreatedOnDateを削除するには、既存のすべてのプロパティと最後$projectを維持しながら、新しいフィールドを追加しCreatedOnDate$addFieldsのステージを使用することができます。

シェル問合せ:

{ 
    "$addFields": { 
     "CreatedOnDate": { 
      "$dateToString": { 
       "format": "%Y-%m-%d", 
       "date": { 
        "$add": ["$CreatedOn", 18000000] 
       } 
      } 
     } 
    } 
}, { 
    "$match": { 
     "CreatedOnDate": { 
      "$gte": "2017-03-31", 
      "$lte": "2017-03-31" 
     } 
    } 
}, { 
    "$project": { 
     "CreatedOnDate": 0 
    } 
} 

C#コード:同上

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 03, 31); 

var addFields = BsonDocument.Parse("{$addFields: { CreatedOnDate: { $dateToString: { format: '%Y-%m-%d', date: {$add: ['$CreatedOn', 18000000] }} }} }"); 

var match = new BsonDocument("CreatedOnDate", new BsonDocument("$gte", start.ToString("yyyy-MM-dd")).Add("$lte", end.ToString("yyyy-MM-dd"))); 

var project = new BsonDocument 
    { 
     { "CreatedOnDate", 0 } 
    }; 

var pipeline = collection.Aggregate().AppendStage<BsonDocument>(addFields) 
    .Match(match) 
    .Project(project); 

var list = pipeline.ToList(); 

List<Student> searchResult = list.Select(doc => BsonSerializer.Deserialize<Student>(doc)).ToList(); 

モンゴバージョン= 3.2

が、このパイプラインが$projectを使用していますので、あなたはすべて追加する必要がありますあなたが最終的な応答で保持したいフィールド。

シェル問合せ:

{ 
    "$project": { 
     "CreatedOn": 1, 
     "Description": 1, 
     "CreatedOnDate": { 
      "$dateToString": { 
       "format": "%Y-%m-%d", 
       "date": { 
        "$add": ["$CreatedOn", 18000000] 
       } 
      } 
     } 
    } 
}, { 
    "$match": { 
     "CreatedOnDate": { 
      "$gte": "2017-03-31", 
      "$lte": "2017-03-31" 
     } 
    } 
}, { 
    "$project": { 
     "CreatedOn": 1, 
     "Description": 1 
    } 
} 

C#コード:

var start = new DateTime(2017, 03, 31); 
var end = new DateTime(2017, 03, 31); 

var project1 = new BsonDocument 
    { 
     { "CreatedOn", 1 }, 
     { "Description", 1 }, 
     { "CreatedOnDate", new BsonDocument("$dateToString", new BsonDocument("format", "%Y-%m-%d") 
          .Add("date", new BsonDocument("$add", new BsonArray(new object[] { "$CreatedOn", 5 * 60 * 60 * 1000 })))) 
     } 
    }; 

var match = new BsonDocument("CreatedOnDate", new BsonDocument("$gte", start.ToString("yyyy-MM-dd")).Add("$lte", end.ToString("yyyy-MM-dd"))); 

var project2 = new BsonDocument 
    { 
     { "CreatedOn", 1 }, 
     { "Description", 1 } 
    }; 


var pipeline = collection.Aggregate() 
.Project(project1) 
.Match(match) 
.Project(project2); 

var list = pipeline.ToList(); 

List<Student> searchResult = list.Select(doc => BsonSerializer.Deserialize<Student>(doc)).ToList(); 

更新4 - 昼光の削減と連動日のみの比較。

モンゴバージョン= 3.6

すべてのアカウントに日光省変化の世話をする必要がありますタイムゾーンの代わりに、固定オフセットがかかります$dateToStringを期待して同じままです。

シェルアップデート:

{ 
    "$addFields": { 
     "CreatedOnDate": { 
      "$dateToString": { 
       "format": "%Y-%m-%d", 
       "date": "$CreatedOn", 
       "timezone": "America/New_York" 
      } 
     } 
    } 
} 

C#のアップデート:

var addFields = BsonDocument.Parse("{$addFields: { CreatedOnDate: { $dateToString: { format: '%Y-%m-%d', date: "$CreatedOn", "timezone": "America/New_York"} }} }"); 
+0

私はあなたの答えでどのように使用するのですか、時間の部分も保存したい、あなたはDateTime.Nowを使用していません –

+0

例に時間部分を追加しました。比較クエリには、答えの 'Update'部分から' filterDefinition'を使います。 – Veeram

+0

daterangepickerの使用よりもサーバー側の日付を除外しなければならない場合クライアント側でそれを行うことはできますか? –

関連する問題