Учитывая следующие данные:
let tasks = [
{
_id: 1,
task_number: 1,
description: 'Clean Bathroom',
customer: 'Walmart',
users_worked: [
{user: 'Jonny', hours: 1},
{user: 'Cindy', hours: 1}
],
supplies_used: [
{item_code: 'LD4949', description: 'Liquid Detergent', quantity: 1}
]
},
{
_id: 2,
task_number: 2,
description: 'Stock Cheeses',
customer: 'Walmart',
users_worked: [
{user: 'Mark', hours: 3.0},
{user: 'Shelby', hours: 2.0}
],
supplies_used: []
}
];
Предположим, я хочу показать таблицу с каждым из них в виде списка:
task_number | description | customer | users | users_worked.hours (sum) | supplies_used.quantity (sum)
----------------------------------------------------------------------------------------------
1 | 'Clean Bathroom' | 'Walmart' | 'Jonny, Cindy' | 2 | 1
2 | 'Stock Cheeses' | 'Walmart' | 'Mark, Shelby' | 5 | 0
Совокупность:
[
{
"unwind: {
"path": "$users_worked",
"preserveNullAndEmptyArrays": true
}
},
{
"unwind: {
"path": "$supplies_used",
"preserveNullAndEmptyArrays": true
}
},
{
$group: {
_id: "$_id",
task_number: {
$first: "$task_number"
},
description: {
$first: "$description"
},
customer: {
$first: "$customer"
},
users: {
$push: "$users_worked.user"
},
users_worked: {
$sum: "$users_worked.hours"
},
supplies_used: {
$sum: "$supplies_used.quantity"
}
}
]
Проблема в том, что мне нужно $unwind
оба массива (users_worked
и supplies_used
), что приводит к искажению моих результатов (декартово произведение). Поскольку у задачи № 1 есть 2 элемента в массиве users_worked
, мой счетчик supplies_used
перейдет к 2.
Это простой пример, может быть много массивов, и чем больше элементов каждый имеет большеэто искажает данные.
Есть ли способ с агрегатами разматывать несколько массивов по отдельности, чтобы они не искажали друг друга? Я видел пример создания 1 комбинированного объекта, в котором был только 1 источник раскручивания. Кажется, я не понимаю, как делать то, что я хочу.
* РЕДАКТИРОВАТЬ *
Я вижу, что вы можете использовать команду $zip
mongo aggregate для объединениянесколько массивов в 1 массив. Это хорошее начало:
arrays: {
$map: {
input: {
$zip: {
inputs: [
'$users_worked',
'$supplies_used'
],
}
},
as: 'zipped',
in: {
users_worked: {
$arrayElemAt: [
'$$zipped',
0
]
},
supplies_used: {
$arrayElemAt: [
'$$zipped',
1
]
}
Как я могу использовать эту команду $zip
, если бы у меня был массив массивов. Например:
let tasks = [
{
_id: 1,
task_number: 1,
description: 'Clean Bathroom',
customer: 'Walmart',
users_worked: [
{user: 'Jonny', hours: 1},
{user: 'Cindy', hours: 1}
],
supplies_used: [
{item_code: 'LD4949', description: 'Liquid Detergent', quantity: 1}
],
invoices: [
{
invoicable: true,
items: [
{item_code: 'LD4949', price: 39.99, quantity: 1, total: 39.99},
{item_code: 'Hours', price: 50.00, quantity: 2, total: 100.00}
]
}
]
},
{
_id: 2,
task_number: 2,
description: 'Stock Cheeses',
customer: 'Walmart',
users_worked: [
{user: 'Mark', hours: 3.0},
{user: 'Shelby', hours: 2.0}
],
supplies_used: [],
invoices: []
}
];
И я хочу включить сумму invoices.items.total в мой список.