当前位置: 首页 > 知识库问答 >
问题:

如何在MongoDB集合中分别对几个月的数据求和

施弘壮
2023-03-14

我试图在集合的子数组中对字段进行计数,我希望每个月都这样做。我曾在Mongo 2.6中使用过此功能,但最近升级到3.0.12导致查询中出现一些错误结果。这几个查询的总和似乎没有重置。

因此,目前我正在异步执行12个查询,并等待它们全部完成。这同样适用于2.6。我的表格结构如下:

{
"_id" : ObjectId("<id>"),
"userId" : ObjectId("<id>"),
"accountId" : "1234567890",
"transactionId" : "22222222333",
"date" : ISODate("2016-09-08T04:00:00.000Z"),
"description" : "SUPERCOOL STORE",
"amount" : -123.45,
"allocations" : [ 
    {
        "jarId" : ObjectId("566faf1937af9ae11ef84bc4"),
        "amount" : -100
    }, 
    {
        "jarId" : ObjectId("566faf1937af9ae11ef84bc1"),
        "amount" : -23.45
    }
],
"reconciled" : true,
"tally" : true,
"split" : true
}

这是我的代码:

var getTransactionAggregate = function (userId, month) {
  var deferred = q.defer();
  var nextMonth = moment(month).add(1, 'M');

  Transactions.aggregate([
    {$match: {
      userId: userId,
      tally: true,
      date: {
        $gte: month.toDate(),
        $lt: nextMonth.toDate()
      }
    }},
    {$project: { _id: 0, allocations: 1 } },
    {$unwind: '$allocations'},
    {$group: {_id: '$allocations.jarId', total: {$sum: '$allocations.amount'}}}
  ]).then(function(data) {
    deferred.resolve(data);
  })
  .catch(function (err) {
    logger.error(err);
    deferred.reject(err);
  });

  return deferred.promise;
};

summaryReport = function (req, res) {
  Jars.aggregate([
    { $match: {userId: new ObjectID(req.user._id)} },
    { $sort: {name: 1} }
  ])
  .then(function (jars) {
    var month = moment(moment().format('YYYY-MM') + '-01T00:00:00.000');
    var i, j;
    var promises = [];

    for (i = 0; i < 12; i++) {
      promises.push(getTransactionAggregate(new ObjectID(req.user._id), month));
      month.add(-1, 'M');
    }

    q.allSettled(promises).then(function (data) {
      for (i = 0; i < data.length; i++) {
        // data[i].value here is returned incorrectly from the queries

        ........
    });
  });
};

因此,从本质上讲,第一个月包含的数据是正确的,但总和似乎继续包含前几个月的数据。如果我分解查询,则会在日期范围内返回正确的事务,并且展开也会起作用。就在groupBy step似乎是罪魁祸首的时候。在我将Mongo升级到3.0.12之前,同样的逻辑运行良好。

是否有更好的方法一次性执行此查询,或者执行12个查询是最好的方法?

共有2个答案

鞠征
2023-03-14

它最终与比赛有关,尽管不是因为上述答案中提到的美元和案例。这与日期匹配有关,我猜是时刻对象。toDate()返回的日期对象与使用new date()时返回的日期对象不同,尽管我认为它们是相同的。

无论如何,工作逻辑如下所示:

Transactions.aggregate([
  {$match: {
    userId: userId,
    tally: true,
    $and: [
      { date: { $gt : new Date(month.toISOString()) } },
      { date: { $lt: new Date(nextMonth.toISOString()) } }
    ]
  }},
  {$unwind: '$allocations'},
  {$group: {_id: '$allocations.jarId', total: {$sum: '$allocations.amount'}}}
])

信用到日期查询与ISODate在mongoDB似乎不工作和@Leif为我指明了正确的方向。

陈正业
2023-03-14

这似乎是$匹配阶段的问题。您的date字段有两个表达式,在这种情况下您需要使用$和运算符,如文档中指定的:

MongoDB在指定逗号分隔的表达式列表时提供隐式AND操作。当必须在多个表达式中指定相同的字段或运算符时,必须使用带有$和运算符的显式AND。

因此它变成:

{$match: {
    userId: userId,
    tally: true,
    $and: [
        { date: { $gte : month.toDate() } },
        { date: { $lt: nextMonth.toDate() } }
    ]
}}
 类似资料:
  • 我正在使用Repast Simphony框架进行模拟。假设我有以下类: 然后我创建了这个类的几个实例,将它们添加到上下文中并运行模拟: 是否有任何方法可以收集聚合数据,但对于类的每个实例分别?我想找出每个生成器的所有生成值的平均值,因此输出统计信息应采用以下格式: 如果我使用方法数据源创建新的聚合(均值)数据集并重复每个刻度,我会得到大量的值列表: 其中每个值都是平均值,但所有生成器的指定刻度值的

  • 有没有一个简单的方法可以做到这一点?

  • 问题内容: MongoDB菜鸟在这里… 好的,我有一个学生集合,每个学生的记录看起来都如下所示:我想按降序对“类型”:“作业”分数进行排序。 mongo外壳上的咒语是什么样的? 我正在尝试这个咒语… 但它不起作用。 问题答案: 您将需要在应用程序代码中或在MongoDB 2.2中使用新的AggregationFramework来操纵嵌入式数组。 Shell中的示例聚合: 样本输出:

  • 我的MongoDB数据库中有一个名为的集合,它由我的Java代码中的接口表示。以下存储库声明使Spring Date查找集合。 我希望它将其配置为使用外部配置在中查找,而不是在上放置注释。这可能吗?我怎么能这么做?

  • 问题内容: 我只想将对象推入mongodb中的对象数组 并将对象推入需要执行的上述文档中 那么我如何使用 mgo驱动程序* 实现相同的功能 * 问题答案: 请尝试以下操作:

  • 本文向大家介绍如何在MongoDB中重命名集合?,包括了如何在MongoDB中重命名集合?的使用技巧和注意事项,需要的朋友参考一下 要在MongoDB中重命名集合,可以使用方法。语法如下- 为了理解上述语法,让我们列出数据库样本中的所有集合。查询如下- 以下是输出- 现在,将集合名称“ informationAboutDelete”更改为“ deleteSomeInformation”。查询如下以