在meteor中使用MongoDB聚合时无法获得正确的结果

时间:2016-03-15 05:36:56

标签: javascript mongodb meteor mongodb-query aggregation-framework

我在meteor中使用MongoDB聚合。

数据库中的项目如下所示:

// item1

{
  products: {
    aaa: 100,
    bbb: 200
  }
}

// item2

{
  products: {
    aaa: 300,
    bbb: 400
  }
}

我的管道看起来像这样

 let pipeline = [{
    $limit: 10
  }, {
    $group: {
      _id: {
        // …
      },
      total: {
        $sum: "$products.aaa"
      }
    }
  }];

它完美无缺。但是,当我将数据库结构更改为此

// item1

{
  products: [
    {code: "aaa", num: 100},
    {code: "bbb", num: 200}
  ]
}

// item2

{
  products: [
    {code: "aaa", num: 300},
    {code: "bbb", num: 400}
  ]
}

我为total得到的结果总是0,我认为我的管道错了。请参阅内部评论:

 let pipeline = [{
    $limit: 10
  }, {
    $group: {
      _id: {
        // …
      },
      total: {
        $sum: "$products.0.num"  // Neither this nor "$products[0].num" works
      }
    }
  }];

那我怎么写得正确呢?感谢

1 个答案:

答案 0 :(得分:1)

使用MongoDB 3.2(不会是带有meteor的捆绑服务器,但是有人会停止使用单独的服务器实例。实际上建议使用)你可以$arrayElemAt使用$map

SELECT CASE WHEN e.emp_type IS NULL OR 
                 e.emp_type = '' OR
                 @emp_type = 'A' 
            THEN 'A' 
            ELSE e.emp_type END AS emp_type  
FROM   t_gc_emp e  
WHERE  @emp_type IN ('A', e.emp_type)

对于旧版本,在使用$group处理后,使用“两个”$first阶段和$unwind运算符。这只是“第一”指数值:

let pipeline = [
    { "$limit": 10 }, 
    { "$group": {
      "_id": {
        // …
      },
      "total": {
        "$sum": { "$arrayElemAt": [
            { "$map": {
                "input": "$products",
                "as": "product",
                "in": "$$product.num"
            }},
            0
        ]}
      }
    }}
];

所以在后一种情况下,在let pipeline = [ { "$limit": 10 }, { "$unwind": "$products" }, { "$group": { "_id": "$_id", // The document _id "otherField": { "$first": "$eachOtherFieldForGroupingId" }, "productNum": { "$first": "$products.num" } }}, { "$group": { "_id": { // … }, "total": { "$sum": "$productNum" } }} ]; 之后你只想使用$unwind从数组中获取“第一个”索引,它也可以用于获取你想要的每个字段用作原始文档中分组键的一部分。将在$first之后为每个数组成员复制所有元素。

在前一种情况下,$unwind只提取每个数组成员的$map值,然后"num"只检索想要的索引位置。

当然,MongoDB 3.2的新方法更好。如果你想要另一个数组索引,那么你需要从数组中重复获取$arrayElemAt元素并继续从数组结果中过滤掉它,直到你达到所需的索引。

因此虽然在早期版本中可行,但要实现目标还需要做很多工作。