1

MongoDBを数ヶ月使用しますが、基本的な使い方で、もっと複雑な関数を使用しようとするのは初めてです。MongoDBで2つのコレクションをマージする

コレクション '取引':

{ "_id" : ObjectId("5878ec66ad251f4fb4d2aacc"), "clubCode" : "43W0K", "date" : ISODate("2017-01-13T15:03:52.410Z"), "symbol" : "ENGI.PA", "name" : "ENGIE SA", "buyOrSell" : "buy", "orderDone" : true, "quantity" : 12, "price" : 11.99, "fees" : 0.99, "total" : 144.87, "__v" : 0 } 
{ "_id" : ObjectId("5878f8c339b47f0ee4a3b80b"), "clubCode" : "43W0K", "date" : ISODate("2017-01-13T15:56:32.088Z"), "symbol" : "PRIO.PA", "name" : "Lyxor ETF PEA Brazil (Ibovespa) C-EUR", "buyOrSell" : "buy", "orderDone" : true, "quantity" : 56, "price" : 8.92, "fees" : 0.99, "total" : 500.51, "__v" : 0 } 
{ "_id" : ObjectId("5878fadf39b47f0ee4a3b80c"), "clubCode" : "43W0K", "date" : ISODate("2017-01-13T16:05:35.849Z"), "symbol" : "ALVIV.PA", "name" : "Visiativ SA", "buyOrSell" : "buy", "orderDone" : true, "quantity" : 10, "price" : 18.15, "fees" : 0.99, "total" : 182.49, "__v" : 0 } 
{ "_id" : ObjectId("587a03319e3fe23138119937"), "clubCode" : "43W0K", "date" : ISODate("2017-01-14T10:52:56.208Z"), "symbol" : "BIG.PA", "name" : "BigBen Interactive", "buyOrSell" : "buy", "orderDone" : false, "orderType" : "ACL", "quantity" : 83, "price" : 6.01, "fees" : 0.99, "total" : 499.82, "__v" : 0 } 

コレクション 'サブスクリプション':

{ "_id" : ObjectId("587c946f3aa3f229a0922761"), "email" : "[email protected]", "clubCode" : "43W0K", "period" : ISODate("2016-09-01T22:00:00Z"), "amount" : 100, "type" : "recurrent", "__v" : 0 } 
{ "_id" : ObjectId("587c946f3aa3f229a0922762"), "email" : "[email protected]", "clubCode" : "43W0K", "period" : ISODate("2016-09-01T22:00:00Z"), "amount" : 100, "type" : "recurrent", "__v" : 0 } 
{ "_id" : ObjectId("587c946f3aa3f229a0922763"), "email" : "[email protected]", "clubCode" : "43W0K", "period" : ISODate("2016-09-01T22:00:00Z"), "amount" : 100, "type" : "recurrent", "__v" : 0 } 

それぞれが(ここでは '43W0K')clubCodeに関連している

は、私は2つのコレクションを持っています。

私は(別のコレクションにまたは単に集計して)、この結果を持っているしたいと思います:

{ 
    clubCode: "43W0K", 
    treasury_moves: [ 
     { 
      date: ISODate("2017-01-13T15:03:52.410Z"), 
      wording: "Achat ENGIE SA", 
      amount: 144.87 
     }, { 
      date: ISODate("2017-01-13T15:56:32.088Z"), 
      wording: "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
      amount: 500.51 
     }, { 
      date: ISODate("2017-01-13T16:05:35.849Z"), 
      wording: "Achat Visiativ SA", 
      amount: 182.49 
     }, { 
      date: ISODate("2017-01-14T10:52:56.208Z"), 
      wording: "Achat BigBen Interactive", 
      amount: 499.82 
     }, { 
      date: ISODate("2016-09-01T22:00:00Z"), 
      wording: "Subscription [email protected]", 
      amount: 100 
     }, { 
      date: ISODate("2016-09-01T22:00:00Z"), 
      wording: "Subscription [email protected]", 
      amount: 100 
     }, { 
      date: ISODate("2016-09-01T22:00:00Z"), 
      wording: "Subscription [email protected]", 
      amount: 100 
     } 
    ] 
} 

だから、「取引」と「サブスクリプション」コレクション間のマージ、

  • date 「取引」の場合は$date、「定期購読」の場合は$periodとなります。
  • wordingは「取引」の場合はAchat $name、の場合は「サブスクリプション」
  • amount結果については、それがすべての「サブスクリプション」

まずにいた場合、それはそれは、これを行うことが可能である、「取引」にあります、または$amount場合$totalに等しいのですか? mapreduceで?集約?

私は類似していると思われるthis topicを探していますが、私が望む結果は得られません。

あなたが私を助けたり、私に従う方法を教えてください。

答えて

1

アグリゲーションフレームワークでaggregate()機能を使用することができます。あなたが希望する結果を得るために、次のパイプラインを実行する必要があります。上記のパイプラインで

db.trades.aggregate([ 
    { 
     "$lookup": { 
      "from": "subscriptions", 
      "localField": "clubCode", 
      "foreignField": "clubCode", 
      "as": "subs" 
     } 
    }, 
    { "$unwind": "$subs" }, 
    { 
     "$group": { 
      "_id": "$clubCode", 
      "trades": { 
       "$push": { 
        "date": "$date", 
        "wording": { "$concat": ["Achat ", "$name"] }, 
        "amount": "$total" 
       } 
      }, 
      "subs": { 
       "$push": { 
        "date": "$subs.period", 
        "wording": { "$concat": ["Subscription ", "$subs.email"] }, 
        "amount": "$subs.amount" 
       } 
      } 
     } 
    }, 
    { 
     "$project": { 
      "clubCode": "$_id", 
      "_id": 0, 
      "treasury_moves": { "$setUnion": ["$subs", "$trades"] } 
     } 
    } 
]) 

サンプル出力

/* 1 */ 
{ 
    "clubCode" : "43W0K", 
    "treasury_moves" : [ 
     { 
      "date" : ISODate("2017-01-13T15:03:52.410Z"), 
      "wording" : "Achat ENGIE SA", 
      "amount" : 144.87 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2017-01-14T10:52:56.208Z"), 
      "wording" : "Achat BigBen Interactive", 
      "amount" : 499.82 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:56:32.088Z"), 
      "wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
      "amount" : 500.51 
     }, 
     { 
      "date" : ISODate("2017-01-13T16:05:35.849Z"), 
      "wording" : "Achat Visiativ SA", 
      "amount" : 182.49 
     } 
    ] 
} 

、第一段階は、$lookupオペレータを必要とします。これにより、「結合された」コレクションのドキュメントを処理するために、同じデータベース内の他のコレクションに「左外部結合」を行うことができます。

db.trades.aggregate([ 
    { 
     "$lookup": { 
      "from": "subscriptions", 
      "localField": "clubCode", 
      "foreignField": "clubCode", 
      "as": "subs" 
     } 
    } 
]) 

では、次の結果を取得します:あなたは ちょうどこの段階でtradesコレクションに対してパイプラインを実行すると次のステップのために

/* 1 */ 
{ 
    "_id" : ObjectId("5878ec66ad251f4fb4d2aacc"), 
    "clubCode" : "43W0K", 
    "date" : ISODate("2017-01-13T15:03:52.410Z"), 
    "symbol" : "ENGI.PA", 
    "name" : "ENGIE SA", 
    "buyOrSell" : "buy", 
    "orderDone" : true, 
    "quantity" : 12, 
    "price" : 11.99, 
    "fees" : 0.99, 
    "total" : 144.87, 
    "__v" : 0, 
    "subs" : [ 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922761"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922762"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922763"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     } 
    ] 
} 

/* 2 */ 
{ 
    "_id" : ObjectId("5878f8c339b47f0ee4a3b80b"), 
    "clubCode" : "43W0K", 
    "date" : ISODate("2017-01-13T15:56:32.088Z"), 
    "symbol" : "PRIO.PA", 
    "name" : "Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
    "buyOrSell" : "buy", 
    "orderDone" : true, 
    "quantity" : 56, 
    "price" : 8.92, 
    "fees" : 0.99, 
    "total" : 500.51, 
    "__v" : 0, 
    "subs" : [ 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922761"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922762"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922763"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     } 
    ] 
} 

/* 3 */ 
{ 
    "_id" : ObjectId("5878fadf39b47f0ee4a3b80c"), 
    "clubCode" : "43W0K", 
    "date" : ISODate("2017-01-13T16:05:35.849Z"), 
    "symbol" : "ALVIV.PA", 
    "name" : "Visiativ SA", 
    "buyOrSell" : "buy", 
    "orderDone" : true, 
    "quantity" : 10, 
    "price" : 18.15, 
    "fees" : 0.99, 
    "total" : 182.49, 
    "__v" : 0, 
    "subs" : [ 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922761"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922762"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922763"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     } 
    ] 
} 

/* 4 */ 
{ 
    "_id" : ObjectId("587a03319e3fe23138119937"), 
    "clubCode" : "43W0K", 
    "date" : ISODate("2017-01-14T10:52:56.208Z"), 
    "symbol" : "BIG.PA", 
    "name" : "BigBen Interactive", 
    "buyOrSell" : "buy", 
    "orderDone" : false, 
    "orderType" : "ACL", 
    "quantity" : 83, 
    "price" : 6.01, 
    "fees" : 0.99, 
    "total" : 499.82, 
    "__v" : 0, 
    "subs" : [ 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922761"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922762"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     }, 
     { 
      "_id" : ObjectId("587c946f3aa3f229a0922763"), 
      "email" : "[email protected]", 
      "clubCode" : "43W0K", 
      "period" : ISODate("2016-09-01T22:00:00.000Z"), 
      "amount" : 100, 
      "type" : "recurrent", 
      "__v" : 0 
     } 
    ] 
} 

を、あなたは平らにする必要があります。次のパイプラインステージとして処理するために$unwindのサブアレイ:

db.trades.aggregate([ 
    { 
     "$lookup": { 
      "from": "subscriptions", 
      "localField": "clubCode", 
      "foreignField": "clubCode", 
      "as": "subs" 
     } 
    }, 
    { "$unwind": "$subs" } 
]) 

これはiが元のコレクション(4)の文書数であり、jが配列要素(3)の数であるi x j文書を生成します。


次のステップ、$groupは、グループ12のclubCodeフィールドによって文書とは、指定されたフィールドからサブ文書を持つ2つのアレイを作成します:パイプラインで

db.trades.aggregate([ 
    { 
     "$lookup": { 
      "from": "subscriptions", 
      "localField": "clubCode", 
      "foreignField": "clubCode", 
      "as": "subs" 
     } 
    }, 
    { "$unwind": "$subs" }, 
    { 
     "$group": { 
      "_id": "$clubCode", 
      "trades": { 
       "$push": { 
        "date": "$date", 
        "wording": { "$concat": ["Achat ", "$name"] }, 
        "amount": "$total" 
       } 
      }, 
      "subs": { 
       "$push": { 
        "date": "$subs.period", 
        "wording": { "$concat": ["Subscription ", "$subs.email"] }, 
        "amount": "$subs.amount" 
       } 
      } 
     } 
    } 
]) 

出力

/* 1 */ 
{ 
    "_id" : "43W0K", 
    "trades" : [ 
     { 
      "date" : ISODate("2017-01-13T15:03:52.410Z"), 
      "wording" : "Achat ENGIE SA", 
      "amount" : 144.87 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:03:52.410Z"), 
      "wording" : "Achat ENGIE SA", 
      "amount" : 144.87 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:03:52.410Z"), 
      "wording" : "Achat ENGIE SA", 
      "amount" : 144.87 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:56:32.088Z"), 
      "wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
      "amount" : 500.51 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:56:32.088Z"), 
      "wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
      "amount" : 500.51 
     }, 
     { 
      "date" : ISODate("2017-01-13T15:56:32.088Z"), 
      "wording" : "Achat Lyxor ETF PEA Brazil (Ibovespa) C-EUR", 
      "amount" : 500.51 
     }, 
     { 
      "date" : ISODate("2017-01-13T16:05:35.849Z"), 
      "wording" : "Achat Visiativ SA", 
      "amount" : 182.49 
     }, 
     { 
      "date" : ISODate("2017-01-13T16:05:35.849Z"), 
      "wording" : "Achat Visiativ SA", 
      "amount" : 182.49 
     }, 
     { 
      "date" : ISODate("2017-01-13T16:05:35.849Z"), 
      "wording" : "Achat Visiativ SA", 
      "amount" : 182.49 
     }, 
     { 
      "date" : ISODate("2017-01-14T10:52:56.208Z"), 
      "wording" : "Achat BigBen Interactive", 
      "amount" : 499.82 
     }, 
     { 
      "date" : ISODate("2017-01-14T10:52:56.208Z"), 
      "wording" : "Achat BigBen Interactive", 
      "amount" : 499.82 
     }, 
     { 
      "date" : ISODate("2017-01-14T10:52:56.208Z"), 
      "wording" : "Achat BigBen Interactive", 
      "amount" : 499.82 
     } 
    ], 
    "subs" : [ 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     }, 
     { 
      "date" : ISODate("2016-09-01T22:00:00.000Z"), 
      "wording" : "Subscription [email protected]", 
      "amount" : 100 
     } 
    ] 
} 

次の2つのアレイに参加し、最終的な集約パイプラインの$setUnionオペレータ、$projectで重複を無視する必要があります。これにより、前のパイプラインの_idキーをclubCodeフィールドに置き換えて文書の形を整えることもできます。これらのステージで最終パイプラインを実行すると、望ましい結果が得られます。

+1

うわー、印象的!ありがとう、それは完全に正常に動作し、私は今理解している(まあ...私は信じて... :))すべての作業! もう一度おねがいします! – Toma

+0

パイプラインについてのさらなる明確化が必要な場合は、コメントに私にpingすることをお気軽に。 – chridam

+0

今のところ、あなたが私に与えるものについて他の質問はありません。 ちょっと別に、結果を日付でソートしたいと思います。私はパイプラインに「並べ替え」を追加しようとしましたが、並べ替えに成功しませんでした。 '$ project'の後に' {$ sort:{treasury_moves.date:1}} 'を置こうとしましたが、うまくいきません。 $ unwindの後に置くと、私は各コ​​レクションをソートできますが、一緒にソートすることはできません。 解決策はありますか? ありがとう! :) – Toma

関連する問題