MongoDB $查找对象数组
MongoDB $lookup on array of objects
类别
{
"_id" : ObjectId("61740086893f048528d166b9"),
"name": "Category1",
"tracks" : [
"61c65353565a2d9a1cd3020d",
"61c74518962dc3efb96c3438",
"61c74775703176a6f72df444"
]
}
曲目
{
"_id" : ObjectId("61c65353565a2d9a1cd3020d"),
"name" : "Track1",
"categoryId" : ObjectId("61740086893f048528d166b9"),
"creatorId" : ObjectId("61c6478304e98ed63e8ee7d3"),
"thumbnailId" : ObjectId("61c65353565a2d9a1cd3020c"),
"plays" : [],
"media" : {
"type" : "wav",
"url" : ""
},
"status" : "approved",
"downloads" : [],
"uploadedDate" : 1640387411
}
假设我有 5 个类别,每个类别都有很多曲目 ID,我想为每个类别获取 N 个最后的曲目,所以我使用了下面的代码
categories.aggregate([
{
$project: {
tracks: { $slice: ["$tracks", -2] },
},
},
]
响应是
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
"61c74518962dc3efb96c3438",
"61c74775703176a6f72df444"
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
到目前为止还不错,但问题是如何将每个类别的曲目从 ID 数组替换为对象数组?
我尝试了 $loopup
,但我可能没有正确实施 localField
。
预期结果
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
{
"_id": ObjectId("61c74518962dc3efb96c3438")
...
},
{
"_id": ObjectId("61c74775703176a6f72df444")
...
}
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
***** 更新 *****
我正在尝试用 createdBy
替换 creatorId
,这是 users
集合
中用户的一个对象
用户
{
"_id": ObjectId("61c6478304e98ed63e8ee7cb"),
"email": "USER888@gmail.com",
"username": "USER999",
"tracks": [
ObjectId("61c65353565a2d9a1cd3020d"),
],
}
预期的结果应该是
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
{
"_id": ObjectId("61c74518962dc3efb96c3438"),
"createdBy": {
"_id": "userId"
...
},
...
},
{
"_id": ObjectId("61c74775703176a6f72df444"),
"createdBy": {
"_id": "userId"
...
}
...
}
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
除了ray下面的解决方案外,我在此处添加了代码https://mongoplayground.net/p/8AjmnL-vhtz
createdBy
在最顶层,但不是在每个轨道下
$lookup
是您在 Tracks
集合中找到相应对象的正确方法。为什么您的代码不起作用是因为您将字符串存储在 Categories
集合中的 tracks
数组中;而 Tracks
集合的 _id
是 ObjectId。由于数据类型不匹配,因此不会有 $lookup
结果。您可以做的是通过在 $map
中使用 $toObjectId
将字符串转换为 ObjectId,然后执行 $lookup
db.categories.aggregate([
{
$project: {
tracks: {
$slice: [
"$tracks",
-2
]
}
}
},
{
$project: {
tracks: {
"$map": {
"input": "$tracks",
"as": "t",
"in": {
"$toObjectId": "$$t"
}
}
}
}
},
{
"$lookup": {
"from": "tracks",
let: {
t: "$tracks"
},
pipeline: [
{
$match: {
$expr: {
"$in": [
"$_id",
"$$t"
]
}
}
}
],
"as": "tracks"
}
}
])
这里是Mongo playground供您参考。
类别
{
"_id" : ObjectId("61740086893f048528d166b9"),
"name": "Category1",
"tracks" : [
"61c65353565a2d9a1cd3020d",
"61c74518962dc3efb96c3438",
"61c74775703176a6f72df444"
]
}
曲目
{
"_id" : ObjectId("61c65353565a2d9a1cd3020d"),
"name" : "Track1",
"categoryId" : ObjectId("61740086893f048528d166b9"),
"creatorId" : ObjectId("61c6478304e98ed63e8ee7d3"),
"thumbnailId" : ObjectId("61c65353565a2d9a1cd3020c"),
"plays" : [],
"media" : {
"type" : "wav",
"url" : ""
},
"status" : "approved",
"downloads" : [],
"uploadedDate" : 1640387411
}
假设我有 5 个类别,每个类别都有很多曲目 ID,我想为每个类别获取 N 个最后的曲目,所以我使用了下面的代码
categories.aggregate([
{
$project: {
tracks: { $slice: ["$tracks", -2] },
},
},
]
响应是
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
"61c74518962dc3efb96c3438",
"61c74775703176a6f72df444"
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
到目前为止还不错,但问题是如何将每个类别的曲目从 ID 数组替换为对象数组?
我尝试了 $loopup
,但我可能没有正确实施 localField
。
预期结果
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
{
"_id": ObjectId("61c74518962dc3efb96c3438")
...
},
{
"_id": ObjectId("61c74775703176a6f72df444")
...
}
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
***** 更新 *****
我正在尝试用 createdBy
替换 creatorId
,这是 users
集合
用户
{
"_id": ObjectId("61c6478304e98ed63e8ee7cb"),
"email": "USER888@gmail.com",
"username": "USER999",
"tracks": [
ObjectId("61c65353565a2d9a1cd3020d"),
],
}
预期的结果应该是
[
{
"_id": "61740086893f048528d166b9",
"tracks": [
{
"_id": ObjectId("61c74518962dc3efb96c3438"),
"createdBy": {
"_id": "userId"
...
},
...
},
{
"_id": ObjectId("61c74775703176a6f72df444"),
"createdBy": {
"_id": "userId"
...
}
...
}
]
},
{
"_id": "61740094893f048528d166c1",
"tracks": []
},
{
"_id": "617400a0893f048528d166cb",
"tracks": []
}
]
除了ray下面的解决方案外,我在此处添加了代码https://mongoplayground.net/p/8AjmnL-vhtz
createdBy
在最顶层,但不是在每个轨道下
$lookup
是您在 Tracks
集合中找到相应对象的正确方法。为什么您的代码不起作用是因为您将字符串存储在 Categories
集合中的 tracks
数组中;而 Tracks
集合的 _id
是 ObjectId。由于数据类型不匹配,因此不会有 $lookup
结果。您可以做的是通过在 $map
中使用 $toObjectId
将字符串转换为 ObjectId,然后执行 $lookup
db.categories.aggregate([
{
$project: {
tracks: {
$slice: [
"$tracks",
-2
]
}
}
},
{
$project: {
tracks: {
"$map": {
"input": "$tracks",
"as": "t",
"in": {
"$toObjectId": "$$t"
}
}
}
}
},
{
"$lookup": {
"from": "tracks",
let: {
t: "$tracks"
},
pipeline: [
{
$match: {
$expr: {
"$in": [
"$_id",
"$$t"
]
}
}
}
],
"as": "tracks"
}
}
])
这里是Mongo playground供您参考。