我想使用两个数组的 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",
}
]
}
我尝试了各种方法,例如 .aggregate()
的 $lookup
或 $unwind
但我无法得到结果。
最佳答案
你想要$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
索引的 first 匹配元素 $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"
}
]
}
但一般来说,任何聚合运算符都没有这样的理由,因为这种操作通常最好留给游标中的后处理。事实上,由于您实际上是在向要返回的文档“添加”数据,因此最好在文档通过网络发送后进行修改。
作为上面显示为 shell 的 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)] }
)
)
}
)
)
产生完全相同的结果,并且通常更容易阅读和解释
关于mongodb - 如何在同一文档中连接数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45625914/