c# - 为什么 MongoDB 查询没有返回任何结果?(按截止日期过滤)
问题描述
这是我的 C# 查询:
public Task<UserStats> GetStatsForUserWithId(string userId, DateTime? cutoffDate = null)
{
var idFilter = Builders<UserStats>.Filter.Eq(s => s.UserId, userId);
var cutoffDateFilter = Builders<UserStats>.Filter.Lt(s => s.Timestamp, cutoffDate ?? DateTime.MaxValue);
return _stats
.Find(idFilter & cutoffDateFilter)
.SortByDescending(stats => stats.Timestamp)
.FirstOrDefaultAsync();
}
这是我试图复制的等效 MongoDB 查询 - 这有效:
db.getCollection('stats').find({
"UserId": "5ca13b15d74d5633c45a3304",
"Timestamp": { $lt: ISODate("2022-04-01T02:17:04+0000") }
}).sort({
"Timestamp": -1
}).limit(1)
这是要存储的实体,以防万一:
public class UserStats
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string UserId { get; set; }
public Stats1V1 Stats1V1 { get; set; }
public Stats2V2 Stats2V2 { get; set; }
public StatsOverall StatsOverall { get; set; }
public DateTime Timestamp { get; set; }
}
问题:当我运行 C# 查询时,我没有得到任何结果。MongoDB 查询工作正常,表明两者之间存在一些我没有看到的差异。它是什么?
这是存储在数据库中的示例对象,省略了不相关的字段以保持简短:
{
"_id" : ObjectId("5ca167ac8c7e7250843553a4"),
"UserId" : "5ca13b15d74d5633c45a3304",
"Stats1V1" : {
// omitted a bunch of fields
},
"Stats2V2" : {
// omitted a bunch of fields
},
"StatsOverall" : {
// omitted a bunch of fields
},
"Timestamp" : ISODate("2019-04-01T01:21:48.861Z")
}
编辑:我应该指出,在添加截止日期过滤器之前,查询运行良好。排序、ID 过滤器等以前工作过,当我添加新的截止日期过滤器时,一切都停止工作了。
解决方案
所以,我在同事的帮助下解决了这个问题。
事实证明,这实际上是由 C# Web API 控制器方法处理未指定的查询参数的方式引起的。我曾假设(对 .NET 来说是新手)就像 C# 中未提供的任何函数参数一样,它默认为 null。但是,对于查询参数,情况显然不是这样 - 它假定我们日历开头的默认值。
我将空值合并到将来某个合理的日期,但此操作永远不会执行,因为该变量实际上从未为空。
当我在调试器中逐步检查它时,我应该已经发现了这一点,但我显然以某种方式错过了它,不知道如何。
但是,我想分享帮助我发现问题原因的信息——我使用 MongoDB 中内置的分析工具来追踪原因。
通过在 MongoDB shell 中运行以下行:
db.setProfilingLevel(0)
db.system.profile.drop()
db.createCollection( "system.profile", { capped: true, size:4000000 } )
db.setProfilingLevel(2)
启用分析,运行我的 API 调用,然后在 Mongo shell 中运行以下行:
db.system.profile.find().pretty()
我能够收到此输出(缩短为重要部分):
"command" : {
"find" : "stats",
"filter" : {
"Timestamp" : {
"$lt" : ISODate("0001-01-01T00:00:00Z")
}
// omitted
请注意,这里的时间戳是 0001 年。这导致我调查它是如何获得该值的,最终由调试器揭示。
希望这种方法将来可以帮助其他人。
推荐阅读
- javascript - Discord.js / Node.js - await 仅在异步函数中有效
- python - Python Tkinter 在一个函数中打开多个窗口
- postgresql - Postgres 访问数据库中的所有内容
- react-native - react-native run-android中的错误
- split - GoogleMaps(或任何)方向 API:将路线分成每 100 公里
- macos - minikube 错误试图在 osx 上达到 172.17.0.4:8080
- javascript - 你将如何将此 for 循环转换为 foreach?这是我正在练习模板字符串的代码
- ios - ImageView 只能在主线程中使用
- c# - T-mobile 和 s9 的 TCP 客户端连接问题
- apache - 如何解决连接 - 过时的连接设置