MongoDB - 使用 C# 驱动程序按日期和时间搜索

Posted

技术标签:

【中文标题】MongoDB - 使用 C# 驱动程序按日期和时间搜索【英文标题】:MongoDB - search by date and time using C# driver 【发布时间】:2016-06-19 13:48:43 【问题描述】:

您好,我想使用 MongoDB 的 C# 驱动程序查找两个日期之间的条目(有时间),但我使用的 Find + Filter 方法会忽略时间并仅按日期搜索(我认为)。我做错了什么?

我的 POCO:

public class TestClassForMongo

    public ObjectId Id  get; set; 
    public DateTime CreatedDateUtc  get; set; 
    public string Message  get; set; 

我的搜索码:

IMongoCollection<TestClassForMongo> collection = db.GetCollection<TestClassForMongo>("mongoTest");

var filterBuilder = Builders<TestClassForMongo>.Filter;
var filter = filterBuilder.Gt("CreatedDateUtc", new DateTime(2016, 03, 04, 21, 0, 0)) &
             filterBuilder.Lt("CreatedDateUtc", new DateTime(2016, 03, 04, 22, 0, 0));
List<TestClassForMongo> searchResult = collection.Find(filter).ToList();

上面的代码返回空数组,虽然这样:

collection.Find(filterBuilder.Empty).First().CreatedDateUtc

返回日期:“2016-03-04 21:21:54”

MongoDB 3.2.3,C# MongoDB 驱动程序 2.2.3

驱动文档:https://docs.mongodb.org/getting-started/csharp/query/

答案:

我没有为任何人提供足够的信息来回答这个问题,问题是时区和 UTC 相关问题,也是非常基本的问题。我使用DateTime.UtcNow 将日期存储在数据库中。它存储为"CreatedDateUtc" : ISODate("2016-03-04T21:21:54.836Z")。在 C# 中获取它会返回一个实际上是 UTC 日期的日期(Kind 属性是 UTC),顺便说一句,它由 db 中值的“Z”后缀表示。将此 UTC 日期与新的 DateTime() 进行比较没有多大意义,因为后者会在您的时区中创建一个日期,该日期可能与 +0 (UTC) 不同。

因此,一种选择是为过滤器创建日期,如下所示:

 new DateTime(2016, 03, 04, 21, 0, 0).ToUniversalTime()

或者修改小时部分以适应时区差异,在我的示例中它将增加 1 小时(因为我在 +1 时区)。

所以实际上存储的时间在我的时区是22:21:54。如果我使用在我的时区创建的日期在 22:00:00 到 23:00:00 之间进行搜索,我会得到正确的结果。

【问题讨论】:

【参考方案1】:

在 dateTime 字段上添加 BSON 属性(见下文),

您可以使用 linqu 语法来构建这样的查询

    var min = new DateTime(2016, 03, 03, 22, 0, 0);
    var max = (new DateTime(2016, 03, 03, 23, 0, 0));
    List<TestClassForMongo> searchResult = collection.Find( 
                x => x.CreatedDateUtc > min &
                x.CreatedDateUtc < max
                ).ToList();

BSON 属性

public class TestClassForMongo

    public ObjectId Id  get; set; 

    [BsonDateTimeOptions]
    public DateTime CreatedDateUtc  get; set; 

    public string Message  get; set; 

linqPad 转储如下:

【讨论】:

这是正确的,我喜欢 linq 风格,但这并没有解决我的问题。这只是创建查询(查找)的另一种方式,基本上返回与过滤器构建器方法相同的内容。 哈!刚刚意识到我没有提供有关 BSON 属性的信息 - 请参阅更新的答案。 BsonDateTimeOptions 会在没有参数的情况下做任何事情吗? 老实说,我在一个示例中添加了它(但不记得在哪里)。没有它我什至没有测试..... 刚刚对我的环境(linqPad 5、win10、mongo 3.2.3)进行了测试,添加/删除属性给了我相同的输出

以上是关于MongoDB - 使用 C# 驱动程序按日期和时间搜索的主要内容,如果未能解决你的问题,请参考以下文章

mongodb的日期类型,其他语言怎么插入这个类型的值啊?

Mongodb,按日期差异分组并获取小时

获取行号MongoDB c#

使用 C# 驱动程序以指定顺序从 MongoDB 获取文档 [重复]

使用 C# 驱动程序以指定顺序从 MongoDB 获取文档 [重复]

按日期排序聚合mongodb