Мангуста СУММ сложены - PullRequest
       12

Мангуста СУММ сложены

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

Я пытаюсь сделать тривиальную сумму на mongoDB для подсчета количества цен для одного клиента.

Моя коллекция:

{"_id":"5d973c71dd93adfbda4c7272","name":"Faktura2019006","clientId":"5d9c87a6b9676069c8b5e15b","expiration":"2019-10-02T01:11:18.965Z","price":999999,"userId":"123"},
{"_id":"5d9e07e0b9676069c8b5e15d","name":"Faktura2019007","clientId":"5d9c87a6b9676069c8b5e15b","expiration":"2019-10-02T01:11:18.965Z","price":888,"userId":"123"}

ЧтоЯ пытался:

// invoice.model.js
const mongoose = require("mongoose");

const InvoiceSchema = mongoose.Schema({
  _id: String,
  name: String,
  client: String,
  userId: String,
  expiration: Date,
  price: Number
});

module.exports = mongoose.model("Invoice", InvoiceSchema, "invoice");

и

// invoice.controller.js
const Invoice = require("../models/invoice.model.js");

exports.income = (req, res) => {
  console.log("Counting Income");

  Invoice.aggregate([
    {
      $match: {
        userId: "123"
      }
    },
    {
      $group: {
        total: { $sum: ["$price"] }
      }
    }
  ]);
};

Что происходит:

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

Скорее всего, я просто пропускаю какую-то глупую мелочь, но пытаюсь выяснить это довольнодолгое время безуспешно, поэтому любые советы приветствуются.

1 Ответ

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

Причина, по которой контроллер никогда не завершает свою работу, заключается в том, что вы не заканчиваете процесс ответа (то есть вам нужно использовать объект res и отправить что-то обратно вызывающей стороне).

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

Также, как кто-то указал в комментариях, вам нужно добавить _id: null в вашей группе кукажите, что вы не собираетесь группировать по какому-либо конкретному полю (см. второй пример здесь ).

Наконец, в операторе $sum то, что вы пытаетесь сделать,вам просто нужно снять скобки массива, так как вы хотите суммировать только по одному полю (см. несколько примеров здесь ).

Вот модифицированный код:

// invoice.controller.js
const Invoice = require("../models/invoice.model.js");

exports.income = (req, res) => {
  console.log("Counting Income");

  Invoice.aggregate([
    {
      $match: {
        userId: "123"
      }
    },
    {
      $group: {
        _id: null,
        total: { $sum: "$price" }
      }
    }
  ]).then((response) => {
    res.json(response);
  });
};

Правка для вашего комментария о том, когда возвращается пустой массив.

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

 Invoice.aggregate([
    {
      $match: {
        userId: "123"
      }
    },
    {
      $group: {
        _id: null,
        total: { $sum: "$price" }
      }
    },
    {
      $project: {
        _id: 0,
        total: "$total"
      }
    }
  ]).then((response) => {
    if (response.length === 0) {
      res.json({ total: 0 });
    } else {
      // always return the first (and only) value
      res.json(response[0]);
    }
  });

Здесь, если вы найдете userId из 123, тогда вы получите это как возвращаемое значение:

{
    "total": 1000887
}

Но если вы измените userId, скажем, на 1123, которого нет в вашей БД, результат будет:

{
    "total": 0
}

Таким образом, ваш клиент всегда может использовать один и тот же тип объекта.

Кроме того, причина, по которой я включил этап конвейера $project, заключалась в подавлении поля _id(см. здесь для получения дополнительной информации ).

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