2017-08-11 19 views
1

我想使用兩個數組的ID將數據合併到一個集合中。如何在同一文檔中連接數組?

一個例子如下所示。

{ 
    "_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", 

     } 
    ] 
} 

我已經試過各種事情像$lookup.aggregate()$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理想:

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" 
     } 
     } 
    } 
    }} 
]) 

這基本上抓住通過$arrayElemAt用於匹配的「指數」從另一個數組值由$indexOfArray返回。

如果您的MongoDB需要回落版本,而不該操作員,那麼你可以使用$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" 
     } 
     } 
    } 
    }} 
]) 

哪裏基本上你$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

謝謝,我得到參考,所以謝謝你 –

相關問題