Как я могу показать пропущенные месяцы в агрегате mon go как себя с 0 для значения? - PullRequest
0 голосов
/ 14 февраля 2020

Как видно из заголовка, я хочу, чтобы месяцы, отсутствующие в совокупном результате, возвращали BruteAmount равно нулю.

Цель

Целью этого кода является создание массива с названиями месяцев и другого с его BruteAmounts, упорядоченного по текущей дате и показывающего прошлое значения года, за исключением текущего месяца.

Задача

Проблема, с которой я столкнулся, заключается в том, что пока все работает, как задумано, когда нет экземпляров $ сопоставить конвейер, месяц пропущен, и я не могу найти способ исправить это.
В своих попытках решить эту проблему я рассмотрел ответы внутри агрегата и при постобработке полученных массивов, оба без успех.

Здесь я добавляю полный код, потому что я не совсем уверен, что то, что я хочу, может быть сделано только внутри агрегата, как указано.

const Order = require('../models/Order');
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];

module.exports = {
    async index(req, res) {
        let currentYear = new Date();
        currentYear.setFullYear(currentYear.getFullYear());
        let pastYear = new Date();
        pastYear.setFullYear(pastYear.getFullYear()-1);
        pastYear.setMonth(currentYear.getMonth()+1);
        pastYear.setDate(1);

        try{
            const orderResponse = await Order.aggregate([
                { $match: {
                    order_ordered_on:{
                        $gte: pastYear,
                        $lt: currentYear
                    },
                    order_status: 'Delivered'
                }},
                { $group : { 
                    _id: {year: {$year : '$order_ordered_on'}, month: {$month : '$order_ordered_on'}},
                    bruteTotal: { $sum: "$order_total"},
                    count: {$sum : 1},
                }},
                { $sort : {
                    _id : 1
                }},
                { $project: {  
                    _id: 0,
                    date: "$_id",
                    bruteTotal:1,
                    count: 1
                }
            }
            ]).catch(error => {throw error});

            let labels = orderResponse.map(month =>(monthNames[month.date.month - 1]));
            let bruteAmount = orderResponse.map(value => value.bruteTotal);

            res.json({
                labels, data: bruteAmount
            });
        }
        catch(message){
            res.send({ error: true, message: String(message) })
        }
    }
};

Кроме того, стоит упомянуть, что хотя count на этапе $ group присутствует, никогда не используется, я просто использовал его для контроля результатов и проверки.

Как это выглядит сейчас

{
    "labels": [
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
        "January"
    ],
    "data": [
            43964,
            52347.97,
            55272.06,
            40023.21,
            91999.06,
            45559.33,
            45190.14,
            54298.52,
            73056.14,
            31517.5,
            31453.56
    ]
}  

Что я хочу

{
    "labels": [
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
        "January",
        "February",
    ],
    "data": [
            43964,
            52347.97,
            55272.06,
            40023.21,
            91999.06,
            45559.33,
            45190.14,
            54298.52,
            73056.14,
            31517.5,
            31453.56,
            0
    ]
}  

Или, если по какой-либо случайности, любой в прошлом месяце нет продаж, давайте предположим, что в прошлом мае:

{
    "labels": [
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
        "January",
        "February",
    ],
    "data": [
            43964,
            52347.97,
            0,
            40023.21,
            91999.06,
            45559.33,
            45190.14,
            54298.52,
            73056.14,
            31517.5,
            31453.56,
            0
    ]
}  

Кроме того, необработанный ответ mon go (orderResponse) выглядит следующим образом: *

{
    "orderResponse": [
        {
            "bruteTotal": 43964,
            "count": 108,
            "date": {
                "year": 2019,
                "month": 3
            }
        },
        {
            "bruteTotal": 52347.97,
            "count": 137,
            "date": {
                "year": 2019,
                "month": 4
            }
        },
        {
            "bruteTotal": 55272.06,
            "count": 150,
            "date": {
                "year": 2019,
                "month": 5
            }
        },
        {
            "bruteTotal": 40023.21,
            "count": 119,
            "date": {
                "year": 2019,
                "month": 6
            }
        },
        {
            "bruteTotal": 91999.06,
            "count": 142,
            "date": {
                "year": 2019,
                "month": 7
            }
        },
        {
            "bruteTotal": 45559.33,
            "count": 151,
            "date": {
                "year": 2019,
                "month": 8
            }
        },
        {
            "bruteTotal": 45190.14,
            "count": 122,
            "date": {
                "year": 2019,
                "month": 9
            }
        },
        {
            "bruteTotal": 54298.52,
            "count": 146,
            "date": {
                "year": 2019,
                "month": 10
            }
        },
        {
            "bruteTotal": 73056.14,
            "count": 166,
            "date": {
                "year": 2019,
                "month": 11
            }
        },
        {
            "bruteTotal": 31517.5,
            "count": 64,
            "date": {
                "year": 2019,
                "month": 12
            }
        },
        {
            "bruteTotal": 31453.56,
            "count": 74,
            "date": {
                "year": 2020,
                "month": 1
            }
        }
    ]
}

1 Ответ

0 голосов
/ 14 февраля 2020

Хорошо, у вас есть несколько вариантов. Я не эксперт по совокупности, поэтому я не буду комментировать, как получить это в том порядке, в каком вы хотите.

Обновите ваши данные, чтобы вам было легче работать. Если вам не нужно иметь его как два массива (помните, что вы всегда можете использовать Object.keys () для получения массива), вы можете использовать оператор распространения

2, но карты не эффективны в любом случае. Давайте попробуем это:

resData = {  
  0: {label: 'jan', data: 0},
  1: {label: 'feb', data: 0}
  2: {label: 'mar', data: 0}
  // so on
  11: {label: 'dec', data: 0}
}
let labels = orderResponse.forEach(e => {

  resData[e.date.month] = {
    label: monthNames[e.date.month - 1],
    data: e.bruteTotal
  }
});

Это будет выглядеть как массив resData[1], который получит метку и данные для jan.

Это не в порядке, основанном на текущем месяце. Однако это то, что пользовательский интерфейс мог бы легко обработать, получив текущий месяц и начав там l oop. Просто не забудьте остановиться на 11 и вернуться к 0.

Это гораздо более типичный объект данных, возвращаемый в пользовательский интерфейс с меткой рядом с данными. Надеюсь, это сработает.


Иногда просто не то, что вам нужно. Я думаю, что это можно сделать как два массива. это просто намного сложнее, и я думаю, что у него будет куча ошибок в граничном регистре.

После того, как ваши карты, вам снова придется l oop над ними, что-то вроде этого

labels.forEach((l, i) => {
  let monthIndex = monthNames.indexOf(l);
  if (labels[i+1] !== monthNames[monthIndex+1]) {
    labels.splice(i+1, 0, monthNames[monthIndex+1]);
    bruteAmount.splice(i+1, 0, 0);
  }
});

Если поставить это после ваших карт, то может работать, но это потребует некоторого тестирования и, вероятно, некоторой работы в пограничном регистре. Что произойдет, если вы пропустили 1-й или последний. Я не знаю, я не проверял это вообще

...