为什么MongoDB查询没有返回任何结果? (按截止日期过滤)

问题描述 投票:0回答:1

这是我的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# mongodb .net-core mongodb-query mongodb-.net-driver
1个回答
1
投票

所以,我在同事的帮助下解决了这个问题。

事实证明,它实际上是由C#Web API控制器方法处理未指定的查询参数的方式引起的。我曾经假设(对.NET不熟悉)就像C#中未提供的任何函数参数一样,它默认为null。但是,对于查询参数,显然不是这种情况 - 它假定我们日历开头的默认值。

我将空值合并到将来的某个合理日期,但是此操作永远不会执行,因为变量实际上从不为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年。这导致我调查它是如何获得该值的,最终由调试器显示。

希望这种方法可以在将来帮助其他人。

© www.soinside.com 2019 - 2024. All rights reserved.