如何在同一文档中加入数组? [英] How to Join Arrays in the Same Document?
问题描述
我想使用两个数组的ID将数据合并到一个集合中.
I would like to combine the data in one collection using the IDs of the two arrays.
下面显示一个示例.
{
"_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
之类的各种操作,但无法获得结果.
I have tried various things like $lookup
or $unwind
of .aggregate()
but I cannot get the result.
推荐答案
您要 $indexOfArray
理想情况:
You want $map
and $indexOfArray
ideally:
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"
}
}
}
}}
])
Which basically grabs the value from the other array via $arrayElemAt
for the matching "index" returned by $indexOfArray
.
如果您的MongoDB需要回退没有该运算符的版本,则可以使用 $filter
代替:
If your MongoDB needs to fall back a version without that operator, then you could use $filter
instead:
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
结果比较其他数组,并只需使用$arrayElemAt
.
Where basically you $filter
the results down of the other array in comparison and simply return the first matching element by the 0
index with $arrayElemAt
.
In either case, there is no need to "self-join" using $lookup
, and that's just really unnecessary overhead best avoided.
从问题文档中,您将获得以下信息:
From the document in the question you get the following:
/* 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"
}
]
}
尽管如此,一般来讲,根本没有任何聚合运算符的原因,因为通常最好将这种运算留给游标进行后处理.实际上,由于实际上是在向文档添加"数据以返回,所以最好在通过网络发送文档之后进行修改.
Generally speaking though, there is no such reason for any aggregation operators at all, as this sort of operation is generally best left to post-processing in the cursor. In fact since you are actually "adding" data to the document to return, it's better to do modification after the document is sent over the network.
作为上述的常见用法,如外壳程序的JavaScript所示:
As a common idiom of the above shown as JavaScript for the shell:
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)] }
)
)
}
)
)
产生完全相同的结果,并且通常在眼睛上更易于阅读和解释
Produces the exact same result, and is generally a bit easier on the eyes to read and interpret
这篇关于如何在同一文档中加入数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!