#mongodb #aggregation-framework
Вопрос:
В настоящее время я занимаюсь проектом, в котором моя система управления базами данных-MongoDB. Я пишу конвейер агрегации, в котором есть несколько этапов. В настоящее время я борюсь на определенном этапе, когда я хочу получить следующий результат. В MongoDB так много выражений операторов, что я не знаю, какое из них использовать для достижения этой цели. У меня есть коллекция под названием Стили и артикулы, которые выглядят следующим образом:
// Schema for styles
const styles = mongoose.Schema({
id: Number,
productId: Number,
name: String,
sale_price: String,
original_price: String,
default_price: Boolean,
}, {
strict: false,
});
// Schema for skus
const skus = mongoose.Schema({
id: Number,
styleId: Number,
size: String,
quantity: String,
}, {
strict: false,
});
Каждый стиль может иметь несколько артикулов, отношения «один ко многим». В моем конвейере агрегирования я использую $lookup для поиска всех артикулов этого конкретного стиля и добавления нового поля под названием артикулы в документе стили. Я получаю такие результаты после поиска$.
{
"style_id": 1,
"name": "Forest Green amp; Black",
"original_price": "140",
"sale_price": "0",
"default?": true,
"skus": [
{
"id": 37,
"styleId": 1,
"size": "XS",
"quantity": 16
},
{
"id": 38,
"styleId": 1,
"size": "S",
"quantity": 8
}
]
}
Что ожидается, поскольку $lookup возвращает соответствующий массив. Но я хочу, чтобы мой документ стилей выглядел так.
{
"style_id": 1,
"name": "Forest Green amp; Black",
"original_price": "140",
"sale_price": "0",
"default?": true,
"skus": {
"37": {
"styleId": 1,
"size": "XS",
"quantity": 16
},
"38": {
"styleId": 1,
"size": "S",
"quantity": 8
}
}
}
Может ли кто-нибудь дать какое-либо представление о том, как структурировать данные, как описано выше, в конвейере агрегации? Любая помощь будет очень признательна. Заранее спасибо.
Ответ №1:
Вы можете использовать $map
или $reduce
преобразовать объекты в массиве в форму
[
{
k: <key1>
v: <value1>
},
{
k: <key2>
v: <value2>
}
]
Затем используйте $arrayToObject
, который преобразует массив в объект, подобный:
{
<key1>: <value1>,
<key2>: <value2>
}
Вместе это может выглядеть так:
{$addFields: {
skus: {
$arrayToObject: {
$map: {
input: "$skus",
in: {
k: {$toString: "$this.id"},
v: "$this"
}
}
}
}
}}
Комментарии:
1. Джо, большое тебе спасибо за ответ. Я попробовал ваше решение, но возникли трудности с тем, как его реализовать
$reduce
здесь.{ $reduce: { input: skus, initialValue: , in: }}
.. Если у вас есть немного времени, не могли бы вы объяснить немного больше об этом? Но в любом случае, еще раз спасибо.