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)の管理下に私の資産を追跡し、すべてのリスト私は現在の価格で保持している位置。私がしなければならないことは、ポートフォリオの毎日の純および総エクスポージャーを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次元のテーブルにフラット化したいと思っているので、うまくいきません。

+1

を同じことを行うことができますあなたは何を証明することができればSOコミュニティは、より多くのを助けるように傾斜していますそれが動作していないかどうかに関わらず、試してみました。試した質問を表示できますか? – chridam

+0

私は同意します。現在の試行を追加しました –

+0

最初の '$ project'パイプラインの' $ grossExposure'フィールドは、元のドキュメントスキーマにないので、あらかじめ計算されたフィールドをステップしていますか、それはあなたのコンセプトです苦しんでいる? – chridam

答えて

1

バスケットフィールドが配列であるので、あなたは$group集計操作を実行する前に、$unwindを使用して、それを平らにする必要があります。また、$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 } } 
]); 
+0

ありがとうございました。私はそれに行くと報告を返すよ。明らかに、巻き戻しの段階に​​ついて読んでおく必要があります。 –

+0

しかし、それは働いていると思うが、グロスとネットエクスポージャーの計算が整数にダウンキャストされているように見えるので、aumの%が常に<1.0であるため、結果は表示されません。結果にタイプを強制する方法はありますか? –

+0

どういうわけか私は数式を把握していません。それは '' sum(shares * price * fx)/ aum'または 'sum((shares * price * fx)/ aum)'ですか?算術演算子の詳細については、[** docs **](https://docs.mongodb。 – 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 } } 
]);