【问题标题】:Filter Transactions occurring on a set of dates过滤在一组日期发生的交易
【发布时间】:2020-06-23 02:51:17
【问题描述】:

我有一个查询,用于汇总日期内的交易量。 现在我希望使用 $match 来过滤落在一组日期的交易。

日期列 raise_date 是一个时间戳,所以我先使用$toDate 将其转换为日期并将其格式化为日期字符串。

我用于计算日期总金额的工作聚合查询是这样的 -

db.transactions.aggregate([{
    "$group": {
        "_id": {
            "$dateToString": {
                format: "%Y-%m-%d",
                date: {
                    "$toDate": "$raised_date"
                }
            }
        },
        amount_total: {
            $sum: "$amount"
        }
    }
}])

它给了我数据:

{ "_id" : "2019-05-13", "amount_total" : 2000 }
{ "_id" : "2019-05-28", "amount_total" : 78 }
{ "_id" : "2019-09-19", "amount_total" : 3000 }
{ "_id" : "2019-01-05", "amount_total" : 9034 }
{ "_id" : "2019-04-15", "amount_total" : 2600 }
{ "_id" : "2019-11-14", "amount_total" : 2870 }
{ "_id" : "2019-09-16", "amount_total" : 1500 }
{ "_id" : "2019-09-18", "amount_total" : 7200 }
{ "_id" : "2019-04-11", "amount_total" : 106034 }
{ "_id" : "2019-03-13", "amount_total" : 2000 }
{ "_id" : "2019-04-30", "amount_total" : 2302 }
{ "_id" : "2019-01-08", "amount_total" : 4665 }
{ "_id" : "2019-05-03", "amount_total" : 83 }
{ "_id" : "2019-08-03", "amount_total" : 2500 }
{ "_id" : "2019-03-04", "amount_total" : 350930 }
{ "_id" : "2019-12-10", "amount_total" : 1819 }
{ "_id" : "2019-03-12", "amount_total" : 15002 }
{ "_id" : "2019-05-08", "amount_total" : 78 }
{ "_id" : "2019-12-12", "amount_total" : 2370 }

然后我可以像这样根据日期过滤这些交易

db.transactions.aggregate([{
    "$group": {
        "_id": {
            "$dateToString": {
                format: "%Y-%m-%d",
                date: {
                    "$toDate": "$raised_date"
                }
            }
        },
        amount_total: {
            $sum: "$amount"
        }
    }
},
{
    $match: {
        _id: {
            $in: ["2019-05-13"]
        }
    }
}])

这给了我数据:

{ "_id" : "2019-05-13", "amount_total" : 2000 }

我认为最好在聚合之前过滤数据,在大表中,所以我希望在开始时添加一个 $match 查询。

现在我正在尝试修改它以使用匹配查询根据一组日期过滤数据。如何过滤需要修改列中值的记录并检查它们是否在日期列表中。

db.transactions.aggregate([{
    "$match": {
        {
              "$dateToString": {
              format: "%Y-%m-%d",
              date: {
                  "$toDate": "$raised_date"
              }
          }
        }: {
            $in: ["2019-05-13"]
        }
    }
}, {
    "$group": {
        "_id": {
            "$dateToString": {
                format: "%Y-%m-%d",
                date: {
                    "$toDate": "$raised_date"
                }
            }
        },
        amount_total: {
            $sum: "$amount"
        }
    }
}])  

我还没有在 mongodb 上做很多工作。只是想通了。

感谢任何帮助。

【问题讨论】:

    标签: mongodb aggregation-framework


    【解决方案1】:

    你需要在分组之前运行$match,如果你已经为raised_date字段定义了MongoDB可以应用索引。转换数据后,无法应用索引。

    试试这个:

    db.transactions.aggregate([
      {
        $match: {
          $or: [
            {
              raised_date: {
                $gte: ISODate("2019-01-05T00:00:00Z"),
                $lte: ISODate("2019-01-05T23:59:59Z")
              }
            },
            {
              raised_date: {
                $gte: ISODate("2019-05-13T00:00:00Z"),
                $lte: ISODate("2019-05-13T23:59:59Z")
              }
            }
          ]
        }
      },
      {
        "$group": {
          "_id": {
            "$dateToString": {
              format: "%Y-%m-%d",
              date: {
                "$toDate": "$raised_date"
              }
            }
          },
          amount_total: {
            $sum: "$amount"
          }
        }
      }
    ])
    

    MongoPlayground

    注意:过滤raised_date日期转换成字符串应该匹配$expr这样的操作符:

    db.transactions.aggregate([
      {
        "$match": {
          $expr: {
            $in: [
              {
                "$dateToString": {
                  format: "%Y-%m-%d",
                  date: {
                    "$toDate": "$raised_date"
                  }
                }
              },
              [
                "2019-05-13", "2019-01-05"
              ]
            ]
          }
        }
      },
      {
        "$group": {
          "_id": {
            "$dateToString": {
              format: "%Y-%m-%d",
              date: {
                "$toDate": "$raised_date"
              }
            }
          },
          amount_total: {
            $sum: "$amount"
          }
        }
      }
    ])
    

    MongoPlayground

    【讨论】:

      【解决方案2】:

      我使用项目将时间戳转换为日期,然后使用日期列表过滤它们,然后进行聚合。

      [{
          $project: {
              "raised_date": {
                  "$dateToString": {
                      format: "%Y-%m-%d",
                      date: {
                          "$toDate": "$raised_date"
                      }
                  }
              },
              "amount": 1
          }
      }, {
          $match: {
              raised_date: {
                  $in: ["2019-05-13", "2019-01-05"]
              }
          }
      }, {
          "$group": {
              "_id": "$raised_date",
              amount_total: {
                  $sum: "$amount"
              }
          }
      }]
      

      如果有更好的方法可以做到这一点,请将其发布为被接受的答案。

      【讨论】:

        【解决方案3】:

        在聚合函数之后,你必须使用投影方法来回答

        【讨论】:

          猜你喜欢
          • 2022-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-04-24
          • 1970-01-01
          • 2017-11-22
          • 2021-11-26
          • 2020-11-17
          相关资源
          最近更新 更多