我有一个类别为DateTime
的类:
class Model {
public DateTime Date { get; set; }
}
在mongo数据库中,它存储为:
"Date" : "2018-02-01T13:22:08Z"
代码:
var builder = Builders<Model>.Filter;
var filter = builder.In("Date", new[]
{
"2018-02-01T13:22:08Z"
});
// Returns zero element list
_collection.Find(filter).ToList();
有趣的是:
var workingFilter = new BsonDocument()
{
{ "Date", "2018-02-01T13:22:08Z"}
};
// This one actually works
_collection.Find(workingFilter).ToList();
我认为当我提供Builder
作为string
字段的值来查询时,Mongo的DateTime
实用程序存在问题。
答案 0 :(得分:1)
首先,您的.NET DateTime
存储为MongoDB string
,这不是默认行为。默认情况下,您应该能够在数据库中看到类似这样的内容:
"Date" : ISODate("2018-02-01T13:22:08Z")
因此,数据库中存储的类型与模型中的类型之间不匹配。请记住,MongoDB在值之前检查类型,并且没有像JavaScript那样的隐式强制转换。
在您的工作示例中,您使用了handles dynamic documents和BsonDocument
,因此驱动程序只是忽略了模型中指定的数据类型,并将其转换为
db.yourCollection.find({"Date" : "2018-02-01T13:22:08Z"})
并返回该文档。
第二个代码段使用通用的Filter
Builder
,因此您指定要关心Model
类中的类型。
您可以在2级上启用MongoDB分析器,然后运行.NET代码:
db.setProfilingLevel(2)
然后,您可以在数据库上运行以下查询:
db.system.profile.find({ns: "yourdb.yourcollection"}).sort({ts:-1}).limit(1).pretty()
,您将看到由驱动程序生成的查询:
"command" : {
"find" : "yourcollection",
"filter" : {
"Date" : {
"$in" : [
ISODate("2018-02-01T13:22:08Z")
]
}
},
"$db" : "yourdb"
}
因此,您可以看到驱动程序知道DateTime
并将字符串转换为ISODate
,这会导致数据库查询级别的类型不匹配,这就是为什么没有得到结果的原因。
解决方案?将您的.NET DateTime
作为ISODate
存储在MongoDB中(推荐),或者始终使用BsonDocument
来构建查询。
答案 1 :(得分:-1)
在C#中使用BsonDateTime
代替DateTime
。如果您想向C#用户公开.NET DateTime,并且仍将日期作为Mongo中的日期持久化,请创建针对同一后备存储获取/设置的两个属性,并使用某些Mongo属性不持久化本机DateTime和重命名BsonDateTime。