2017-04-02 101 views
7

我使用MongoDB的C#最新的驅動程序即3 +在我的項目。我有不同的日期過濾標準像今天最後一天,昨天,本月等使用daterangepicker。過濾器只能通過使用日期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(); 

此代碼工作正常,但是當我選擇今天的篩選,然後日期變成

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"), 

這是我正在使用的日期過濾器。我應該有subract -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中查看日期時間時,你總是必須將偏離當地時區的因子考慮在內。

您將始終在當地時區發送日期。蒙戈C#驅動程序之前,堅持從本地更改時間UTC。

例如

當我保存CreatedOn = 2017-04-05 15:21:23.234(當地時區(美國/芝加哥)),但 文檔當你看到在DB你會看到一些ISODate("2017-04-05T20:21:23.234Z")即本地時間與UTC這是抵消的文件-5個小時。

[BsonDateTimeOptions(Kind = DateTimeKind.Local)]指示驅動程序將時間從UTC轉換爲當地時間,然後將BSON返回到您的POCO。

下面是測試情況解釋的行爲。

代碼:

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); 

這得到發送到服務器作爲$gteISODate("2017-03-31T00:00:00.000+05:00")$lteISODate("2017-03-31T00:00:00.000+05:00")和它不發現上面的條目。

正確的方法來查詢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); 

所以,現在你的範圍查詢發送到服務器$gteISODate("2017-03-31T00:00:00.000+05:00")$ltISODate("2017-04-01T00:00:00.000+05:00")你應該能夠找到今天的所有比賽。

更新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); 

所以,現在你的範圍查詢發送到服務器$gteISODate("2017-03-31T00:00:00.000+05:00")$lteISODate("2017-03-31T00:00:00.000+05:00"),你應該能夠找到所有今天比賽。

更新3 - 僅限日期使用BsonDocument進行比較。

這裏的想法是添加區偏移量是+5:00服務器的UTC日期和變換計算的日期時間使用$dateToSting運營商隨後在相同格式的輸入字符串日期比較字符串yyyy-MM-dd格式。

這會在你的時區工作,但不會DST工作觀測時區。

蒙戈3.4版本

您可以使用$addFields階段它增加了新的領域CreatedOnDate同時保持所有現有的屬性和最後$project從最終反應比較後丟棄CreatedOnDate

殼牌查詢:

{ 
    "$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

添加時間部分的例子。從比較查詢的答案的「更新」部分使用'filterDefinition'。 – Veeram

+0

如果我不得不在服務器端過濾日期而不是使用daterangepicker的日期。我可以在客戶端做到嗎? –