【问题标题】:Mongo: dates in match aggregate query seem to be ignoredMongo:匹配聚合查询中的日期似乎被忽略了
【发布时间】:2021-06-22 12:32:41
【问题描述】:

我正在尝试在我的 mongo 数据库中运行聚合语句。我有一份文件,其结构(至少)如下:

{
   "_id": ObjectId,
   "date": ISODate,
   "keywordGroupId": NumberLong,
   "ranking": NumberLong,
}

我想运行一个聚合语句,聚合给定“keywordGroupId”和给定“日期”间隔的“排名”字段。

我一直在尝试使用以下聚合命令:

{ 
    aggregate : "KeywordHistory", 
    pipeline : [
        { $match: { keywordGroupId: 75 , "$date": {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}} },
        { $group: { _id: { null }, count: { $sum: "$ranking" } } }
    ]
}

此命令执行没有错误并返回结果。如果我尝试更改“keywordGroupId”字段的值,该命令将返回不同的值,因此我假设 $match 语句适用于该字段 (NumberLong)。但是,如果我更改“日期”范围并指定数据库中没有任何数据的时间间隔,它仍然会返回结果(我实际上希望得到一个空的结果集)。所以我必须假设 $match 语句忽略了指定的日期间隔。

谁能帮我解决这个问题?

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    删除$match$date 字段上的$ 前缀:

    { $match: { 
        keywordGroupId: 75, 
        date: {$gte: ISODate("2013-01-01T00:00:00.0Z"), $lt: ISODate("2013-02-01T00:00:00.0Z")}
    }},
    

    当字段名称用于值而不是键时,您只能使用 $ 前缀。

    【讨论】:

    • 我已经尝试不使用$,但它不起作用。实际上,如果我删除它,查询总是返回一个空的结果集(即使我使用数据库中的日期间隔)。
    • 我希望包含以下两个文档:{ "_id": ObjectId("511e2dca73ff275f250002e9"), "date": ISODate("2013-01-06T00:00:00.0Z"), "keywordGroupId": NumberLong(75), "ranking": NumberLong(13) } and { "_id": ObjectId("511e2dca73ff275f250002e8"), "keywordGroupId": NumberInt(75), "date": ISODate("2013-01-15T00:00:00.0Z"), "ranking": NumberInt(11) }
    • 虽然,我不希望结果中出现以下结果:{ "_id": ObjectId("511e2dca73ff275f250002e8"), "keywordGroupId": NumberInt(75), "date": ISODate("2012-12-16T00:00:00.0Z"), "ranking": NumberInt(11) }。如果我运行上面的聚合命令(使用 $date),它也会返回上面的文档,即使它不应该包含在内,因为日期不在所需/表示的时间范围内。
    • @Marco 您不想包含的那个文档与 1-15 具有相同的 _id。但是在修复之后,聚合工作正常,只返回两个文档。
    • 抱歉,为方便起见,我复制了它,只更改了结果中应包含的文档之一的字段日期。我只是再次运行聚合命令来检查 _id 是否都是唯一的并且它们是唯一的。这是一个不应该出现在我的结果集中的文档(我只想要一月份的数据)但它仍然包含在其中:{ "_id": ObjectId("511e2dc773ff275f25000253"), "keywordGroupId": NumberInt(75), "date": ISODate("2013-02-06T00: 00: 00.0Z"), "ranking": NumberInt(1) }
    【解决方案2】:

    有时 ISodate 不起作用。因此,如果您只想使用“一个”日期来匹配日期,最好的方法是:---

    ex:-- 让架构为:---

        var storeOrder = new Schema({
        store_name:{type:String, required:true},
        date :{type:Date ,default:moment(new Date()).format('YYYY-MM-DD')},
        orders : [{
        vegetable : String,
        quantity : Number,
        price:Number
         }]
    });
    
    
    mongoose.model('storeorder',storeOrder);
    

    现在按匹配日期聚合:--

    storeOrder.aggregate([$match:{date :new Date("2016-12-26T00:00:00.000Z")} ])
    

    **必须使用new Date("2016-12-26T00:00:00.000z"),而不是Date("2016-12-26T00:00:00.000z") because Date(your_date) !== new Date(your_date)

    谢谢你

    【讨论】:

      【解决方案3】:

      聚合需要一个 Javascript 日期对象,否则不起作用。

      new Date();
      new Date(year, month, day);
      

      请注意月份以 0 而不是 1 开头(您的一月是 0 和十二月 11)

      【讨论】:

        猜你喜欢
        • 2021-10-28
        • 2016-09-30
        • 2012-03-11
        • 1970-01-01
        • 1970-01-01
        • 2013-09-12
        • 1970-01-01
        • 2017-12-05
        • 2012-03-08
        相关资源
        最近更新 更多