我有一个数据模型,其中每个产品都有许多变体,每个变体都有许多修改。在数据库中它看起来像这样:
const mods = db.modifications.insertMany([
{
title: 'Modification #1',
image: 'img1.png',
},
{
title: 'Modification #2',
image: 'img2.png',
},
{
title: 'Modification #3',
image: 'img3.png',
},
])
db.products.insertOne({
slug: 'product1',
title: 'Product #1',
variants: [
{
size: 20,
price: 200,
modifications: [
{ id: mods.insertedIds[0], price: 10 },
{ id: mods.insertedIds[1], price: 15 },
],
},
{
size: 30,
price: 250,
modifications: [
{ id: mods.insertedIds[0], price: 15 },
{ id: mods.insertedIds[2], price: 20 },
],
},
],
})
https://mongoplayground.net/p/6jmEv2Q2aZO
我想做的是
db.products.aggregate([
{ $match: { slug: 'product1' } },
// ?
])
得到如下所示的结果
const result = {
slug: 'product1',
title: 'Product #1',
variants: [
{
size: 20,
price: 200,
modifications: [
{ _id: '…', title: 'Modification #1', image: '…', price: 10 },
{ _id: '…', title: 'Modification #2', image: '…', price: 15 },
],
},
{
size: 30,
price: 250,
modifications: [
{ _id: '…', title: 'Modification #2', image: '…', price: 15 },
{ _id: '…', title: 'Modification #3', image: '…', price: 20 },
],
},
],
}
如何在 MongoDB 中实现?
我尝试过
$unwind
两次,然后$lookup
db.products.aggregate([
{ $match: { slug: 'product1' } },
{ $unwind: '$variants' },
{ $unwind: '$variants.modifications' },
{
$lookup: {
from: 'modifications',
localField: 'variants.modifications.id',
foreignField: '_id',
let: { price: '$variants.modifications.price' },
pipeline: [{ $addFields: { price: '$$price' } }],
as: 'modifications',
},
},
])
但不知道如何
$group
(?)恢复该数据。
此外,还有 具有工作解决方案的类似问题。但就我而言,
modifications
数组不仅仅是 id 数组,而且在其元素(price
字段)中包含数据,我需要以某种方式将其包含在结果中。
无需
$unwind
阶段即可实现。
$match
$lookup
- 从 modifications 集合中使用 _id
获取匹配的文档 modIds
(variants.modifications.id)
)并输出为 modifications
数组。
$set
- 设置 variants
字段。
3.1。
$map
- 通过合并当前 variants
(变体)对象和结果 3.1.1中的对象来迭代
v
数组。
3.1.1.
$map
- 通过迭代 modifications
数组,合并当前 modifications
(修改)对象和结果 3.1.1.1中的对象,该对象包含
m
数组。
3.1.1.1。
$first
- 从结果中获取第一个匹配元素3.1.1.1.1.
3.1.1.1.1。
$filter
- 使用 modifications
从(根)m.id
数组中过滤匹配文档。
$unset
- 删除“modifications”和“variants.modifications.id”字段。
db.products.aggregate([
{
"$match": {
slug: "product1"
}
},
{
"$lookup": {
"from": "modifications",
"let": {
modIds: {
$reduce: {
input: "$variants.modifications.id",
initialValue: [],
in: {
$concatArrays: [
"$$value",
"$$this"
]
}
}
}
},
"pipeline": [
{
"$match": {
$expr: {
$in: [
"$_id",
"$$modIds"
]
}
}
}
],
"as": "modifications"
}
},
{
$set: {
variants: {
$map: {
input: "$variants",
as: "v",
in: {
$mergeObjects: [
"$$v",
{
modifications: {
$map: {
input: "$$v.modifications",
as: "m",
in: {
$mergeObjects: [
"$$m",
{
$first: {
$filter: {
input: "$modifications",
cond: {
$eq: [
"$$this._id",
"$$m.id"
]
}
}
}
}
]
}
}
}
}
]
}
}
}
}
},
{
$unset: [
"modifications",
"variants.modifications.id"
]
}
])