MongoDB 聚合管道问题
MongoDB Aggregation pipeline problems
我是 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
(负仓即为空仓)。我需要使用聚合框架将其作为单个查询来执行。我已经尝试了很多查询,但 none 似乎工作得如此清楚,我只是在黑暗中徘徊。谁能给点指导?
我的查询如下所示
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
}
}
]
);
查询运行但计算值为零。我的投影没有像我预期的那样工作,因为我希望将所有数据展平为二维 table.
由于篮子字段是一个数组,您需要使用 $unwind
before running the $group
aggregate operation. Also, create a new field in the $project
that holds the exposure before the $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 } }
]);
您可以在单阶段对 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 } }
]);
我是 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
(负仓即为空仓)。我需要使用聚合框架将其作为单个查询来执行。我已经尝试了很多查询,但 none 似乎工作得如此清楚,我只是在黑暗中徘徊。谁能给点指导?
我的查询如下所示
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
}
}
]
);
查询运行但计算值为零。我的投影没有像我预期的那样工作,因为我希望将所有数据展平为二维 table.
由于篮子字段是一个数组,您需要使用 $unwind
before running the $group
aggregate operation. Also, create a new field in the $project
that holds the exposure before the $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 } }
]);
您可以在单阶段对 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 } }
]);