我是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
}
}
]
);
查询运行但计算值为零。由于我希望所有数据都被展平为二维表格,因此我的投影无法正常工作。
答案 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 } }
]);