MongoDB раскручивают в параллельных стадиях или объединяют - PullRequest
2 голосов
/ 05 октября 2019

Учитывая следующие данные:

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 в мой список.

Ответы [ 2 ]

3 голосов
/ 05 октября 2019

Вместо использования $unwind и $group вы можете использовать $ уменьшение для объединения имен и $ sum для суммирования чисел:

db.collection.aggregate([
    {
        $project: {
            task_number: 1,
            description: 1,
            customer: 1,
            users: {
                $reduce: {
                    input: "$users_worked",
                    initialValue: "",
                    in: {
                        $concat: [ "$$value", ", ", "$$this.user" ]
                    }
                }
            },
            users_worked: { $sum: "$users_worked.hours" },
            quantity: { $sum: "$supplies_used.quantity" }
        }
    }
])

Детская площадка Монго

0 голосов
/ 08 октября 2019

Мне удалось решить эту проблему, используя несколько слоев $ zip. Начинается с корневого слоя, все массивы в корневом каталоге необходимо сжать, а затем размотать. Затем вы находите $ sum для любых полей в этом слое, затем вы находите следующий слой, $ zip новые массивы, затем раскручиваете, затем суммируете этот слой и т. Д.

Проблема в том, что вы не хотите раскручиватьнесколько массивов или вы получите декартово произведение. Нужно объединить в 1 массив, потом раскрутить, тогда все правильно!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...