MongoDB聚合管道问题

时间:2016-09-14 12:52:08

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

我是mongoDB的新手,我很难理解聚合管道。

我创建了一个数据库,其中包含有关我的股票交易的信息。在一个简化版本中,我的投资组合中的一个文档看起来有点像这样

   {
   "date" : 2015-12-31T15:50:00.000Z,
   "time" : 1550,
   "aum"  : 1000000,
   "basket" :[
   {
     "_id" : "Microsoft",
     "shares" : 10,
     "price"  : 56.53,
     "fx"     : 1.0
   },
   .
   .
   .
   {
     "_id" : "GOOG.N",
     "shares" : 20,
     "price"  : 759.69,
     "fx"     : 1.0
   }

因此,对于每一天,我都会跟踪我管理的资产(aum)以及我用当前价格持有的所有头寸的列表。我需要做的是计算投资组合的每日净敞口和总投资额,作为aum的百分比。净曝光很简单:

sum(shares*price*fx)/aum

超过所有股票。总暴露是:

abs(shares*price*fx)/aum

(负面位置表示空头头寸)。我需要使用聚合框架将此作为单个查询。我已经尝试了大量的查询,但似乎没有一个工作如此清楚,我只是在黑暗中四处游荡。任何人都可以提供一些指导吗?

我的查询看起来像这样

db.strategy.aggregate(

  // Pipeline
  [
    // Stage 1
    {
      $project: {
        "_id": 0,
        "date":1,
        "time":1,
        "aum":1,
        "strategyName":1,
        "gExposure": {$divide: ["$grossExposure","$aum"]}
      }
    },

    // Stage 2
    {
      $group: {
        _id :{ date:"$date",time:"$time",strategyName:"$strategyName"},
        grossExposure: { $sum: { $abs: {$multiply: [ "$basket.sysCurShares","$basket.price","$basket.fx" ] } }}
      }
    },

    // Stage 3
    {
      $sort: {
      "_id.date": 1,  "_id.time": 1,  "_id.strategyName": 1 
      }
    }

  ]
);

查询运行但计算值为零。由于我希望所有数据都被展平为二维表格,因此我的投影无法正常工作。

2 个答案:

答案 0 :(得分:2)

由于购物篮字段是一个数组,因此您需要在运行 $unwind 聚合操作之前使用 $group 将其展平。此外,在 $project 中创建一个新字段,该字段在 $group 管道之前保留曝光。继续您之前的尝试,您可以尝试以下管道:

db.strategy.aggregate([
    { "$unwind": "$basket" },
    {
        "$project": {
            "date": 1,
            "time": 1,          
            "strategyName": 1,
            "exposure": { 
                "$multiply": ["$basket.sysCurShares", "$basket.price", "$basket.fx"] 
            }
        }
    },    
    {
        "$group": {
            "_id": { 
                "date": "$date",
                "time": "$time",
                "strategyName": "$strategyName"
            },
            "totalExposure": { "$sum": "$exposure" },
            "aum": { "$first": "$aum" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "date": "$_id.date",
            "time": "$_id.time",         
            "strategyName": "$_id.strategyName",
            "netExposure": { "$divide": ["$totalExposure", "$aum"] },
            "grossExposure": {
                "$abs": { "$divide": ["$totalExposure", "$aum"] } 
            }
        }
    }, 
    { "$sort": { "date": 1,  "time": 1,  "strategyName": 1 } }
]);

答案 1 :(得分:0)

你可以在单阶段使用mongodb 3.4做同样的事情

db.strategy.aggregate([
{
  $project:{
        "date": 1,
        "time": 1,          
        "strategyName": 1,   
        "netExposure":{ "$divide": [{"$reduce":{input:"$basket",initialValue:0,in:{$add:[{$multiply: ["$$this.fx","$$this.shares","$$this.price"]},"$$value"]}}}, "$aum"] },
        "grossExposure":{"$abs":{ "$divide": [{"$reduce":{input:"$basket",initialValue:0,in:{$add:[{$multiply: ["$$this.fx","$$this.shares","$$this.price"]},"$$value"]}}}, "$aum"] }}
}, 
{ "$sort": { "date": 1,  "time": 1,  "strategyName": 1 } }
]);