1

我是mongoDB的新手,并且难以得到聚集流水线的头像。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)和所有的列表我持有目前的价位。我需要做的是计算投资组合的每日净暴露量和总暴露量,以百分比表示。网曝无非是:

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 
     } 
    } 

    ] 
); 

查询运行,但计算出的值为零。我的预测没有像我期望的那样工作,因为我希望将所有数据拼凑成二维表格。

+1

多所社区倾斜,以帮助更多的,如果你能证明什么你已经尝试过了,不管它是否工作或不工作。你能显示你试过的查询吗? – chridam

+0

我同意。我已经添加了我的当前尝试 –

+0

只需确认,第一个“$ project”管道中的$ grossExposure字段是预先计算的字段,因为它不在原始文档模式中,或者这是您的概念挣扎着? – chridam

回答

1

由于篮领域是一个数组,你需要使用$unwind运行$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 } } 
]); 
+0

非常感谢你。我会放弃并报告。显然,我需要阅读关于放松阶段。 –

+0

我认为这有效,但它看起来像总暴露率和净暴露量的计算被降低到整数,所以我不能看到结果,因为暴露百分比总是<1.0。有没有一种强制结果类型的方法? –

+0

不知何故,我无法掌握公式,它是'(sum(shares * price * fx))/ aum'还是'sum((shares * price * fx)/ aum)'?有关算术运算符的更多详细信息,请参阅[** docs **](https://docs.mongodb。com/manual/reference/operator/aggregation-arithmetic /) – chridam

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 } } 
]);