2017-08-11 6 views
1

2つの配列のIDを使用して1つのコレクション内のデータを結合したいと思います。同じドキュメントで配列を結合するには?

例を以下に示します。

{ 
    "_id": ObjectId ("5976fd2eb0adec0a32fa9831"), 
     "People": [ 
      { 
      "_id": 1,  <--- ID 
      "Name": "jane" 
      }, 
      { 
      "_id": 2,  <--- ID 
      "Name": "Mark" 
      } 
     ], 
     "Contents": [ 
      { 
      "userID": 2, <--- People ID 
      "Text": "111" 
      }, 
      { 
      "userID": 1, <--- People ID 
      "Text": "Hi" 
      } 
     ] 
} 

以下のようにしたいと思います。

{ 
    "_id": ObjectId ("5976fd2eb0adec0a32fa9831"), 
    "People": [ 
     { 
      "_id": 1, 
      "Name" : "Jane" 
     }, 
     { 
      "_id": 2, 
      "Name": "Mark" 
     } 
    ], 
    "Contents": [ 
     { 
      "userID": 2, 
      "Name": "Mark", <-- Adding 
      "Text": "111", 

     }, 
     { 
      "userID": 1, 
      "Name": "Jane", <-- Adding 
      "Text": "Hi", 

     } 
    ] 
} 

私は.aggregate()$lookupまたは$unwindのような様々なものを試してみましたが、私は結果を得ることができません。

+0

を読んで解釈するの目に、一般的に少し楽であるあなたがしようとしたことがありこのリンク?私はそれが助けてくれることを願っています。https://stackoverflow.com/questions/37086387/join-two-collections-on-mutiple-field-using-lookupそしてhttps://www.sitepoint.com/using-joins-in- mongodb-nosql-databases/ – Tehmina

+0

@Tehmina同じ文書内の項目間に「自己結合」する必要はありません。実際には効率が悪く、効果的にコレクションを再クエリする必要はなく、実際にはこれを実行する非常に効果的な方法があります。 –

答えて

0

あなたは理想的$map$indexOfArrayをしたい:

基本的に $indexOfArrayによって返さマッチング「インデックス」のために $arrayElemAtを介して他の配列から値をつかむ
db.collection.aggregate([ 
    { "$addFields": { 
    "Contents": { 
     "$map": { 
     "input": "$Contents", 
     "as": "c", 
     "in": { 
      "userID": "$$c.userID", 
      "Name": { 
      "$arrayElemAt": [ 
       "$People.Name", 
       { "$indexOfArray": [ "$People._id", "$$c.userID" ] } 
      ] 
      }, 
      "Text": "$$c.Text" 
     } 
     } 
    } 
    }} 
]) 

。基本的にあなた$filter結果と比較して他のアレイのダウン

db.collection.aggregate([ 
    { "$addFields": { 
    "Contents": { 
     "$map": { 
     "input": "$Contents", 
     "as": "c", 
     "in": { 
      "userID": "$$c.userID", 
      "Name": { 
      "$arrayElemAt": [ 
       { "$map": { 
       "input": { 
        "$filter": { 
        "input": "$People", 
        "as": "p", 
        "cond": { "$eq": [ "$$p._id", "$$c.userID" ] } 
        } 
       }, 
       "as": "p", 
       "in": "$$p.Name" 
       }}, 
       0 
      ] 
      }, 
      "Text": "$$c.Text" 
     } 
     } 
    } 
    }} 
]) 

を単に最初を返す:あなたのMongoDBは、その演算子なしでバックバージョンを落下する必要がある場合

、その後、あなたの代わりに$filterを使用することができますと一致する要素は0で、インデックスは$arrayElemAtです。

どちらの場合も、$lookupを使用して「自己結合」する必要はありません。

ますが、以下の問題のドキュメントから:操作のこの種は、一般的に最高の左であると一般的に、すべての任意の集計演算子には、このような理由はありません、しかし話す

/* 1 */ 
{ 
    "_id" : ObjectId("5976fd2eb0adec0a32fa9831"), 
    "People" : [ 
     { 
      "_id" : 1.0, 
      "Name" : "jane" 
     }, 
     { 
      "_id" : 2.0, 
      "Name" : "Mark" 
     } 
    ], 
    "Contents" : [ 
     { 
      "userID" : 2.0, 
      "Name" : "Mark", 
      "Text" : "111" 
     }, 
     { 
      "userID" : 1.0, 
      "Name" : "jane", 
      "Text" : "Hi" 
     } 
    ] 
} 

カーソルで後処理することができます。実際には、実際にドキュメントにデータを追加して戻すため、ドキュメントがネットワーク経由で送信された後に変更する方がよいでしょう。上記シェルのためのJavaScriptとして示す共通のイディオムとして

db.collection.find().map(d => 
    Object.assign(
    d, 
    { 
     "Contents": d.Contents.map(c => 
     Object.assign(c, 
      { "Name": d.People.map(p => p.Name)[d.People.map(p => p._id).indexOf(c.userID)] } 
     ) 
    ) 
    } 
) 
) 

はまったく同じ結果を生成し、

+0

ありがとう、私は参照を取得するので、ありがとう –

関連する問題