2017-08-11 42 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

谢谢,我得到参考,所以谢谢你 –

相关问题