0

I have a table called user_feedbacks,

enter image description here

For type we have 4 default values - 1-Suggestion, 2-Request, 3-Damage Report, 4-Incident

For status we have 3 default values - 0-open, 1-in progress, 2-closed

I want to show under each type for each status, count of records like below [Required Output],

{
  "status": "success",
  "code": 200,
  "data": {
    "1"(Type): {
      "0" (status): 20, (total)
      "1": 19,
      "2": 28
    },
    "2": {
      "0": 20,
      "1": 19,
      "2": 28
    },
    "3": {
      "0": 20,
      "1": 19,
      "2": 28
    },
    "4": {
      "0": 20,
      "1": 19,
      "2": 28
    }
  }
}

Below is my code,

In feedback.js

static async getFeedbackStats(opts) {
    assert.object(opts, 'opts')
    assert.func(opts.mysql_db, 'opts.mysql_db')

    const { mysql_db } = opts

    const result = mysql_db.select('type', 'status', mysql_db.raw('count(status)'))
        .from('user_feedbacks')
        .groupBy('status', 'type')

    return result
  }

In handler.js

const assert = require('assert-plus')
const Utils = require('../common/repos/feedbacks')
const Auth = require('../common/auth')
const Logger = require('../common/debug_logger')

async function handler(event, ctx, opts) {
    Logger.info('Feedback stats handler has been invoked: %j', event)

    const auth = await Auth.authenticate(event)

    if (!auth.success){
        return { status : 'failed', code : 401}
    }

    assert('params' in auth, 'auth.params')
    assert('auth_ctx' in auth, 'auth.auth_ctx')
    assert('user_id' in auth.auth_ctx, 'auth.auth_ctx.user_id')

    Logger.info('Feedback stats handler Auth.Params: %j', auth.params)

    const result = await Utils.getFeedbackStats(opts)

    return { status: 'success', code: 200, data: result }

}

module.exports = { handler }

Above code return below output [Output i return],

    {
    "status":"success",
    "code":200,
    "data":[
        {
          "type":1,
          "status":0,
          "count(status)":2
        },
        {
          "type":2,
          "status":0,
          "count(status)":1
        },
        {
          "type":1,
          "status":1,
          "count(status)":1
        },
        {
          "type":1,
          "status":2,
          "count(status)":1
        }
          ]
}

Anyone can helps me to get this output as above output i mention?

  • Shouldn't `Utils.getFeedbackStats` return a promise? Also, it's recommended to wrap async methods in `try catch` blocks. – Emmanuel Gabriel Mar 04 '20 at 21:40
  • @EmmanuelGabriel Utils.getFeedbackStats return output as i mention in question but i'm not sure how to get required output as i mention in top. –  Mar 04 '20 at 21:43
  • I meant you should explicitly return a promise like `return await mysql_db.select('type', 'status', mysql_db.raw('count(status)')) .from('user_feedbacks') .groupBy('status', 'type')` Also, can you show me the exact output of the call to get `Utils.getFeedbackStats`? – Emmanuel Gabriel Mar 04 '20 at 21:49
  • @EmmanuelGabriel this is the output i get - {"status":"success","code":200,"data":[{"type":1,"status":0,"count(status)":2},{"type":1,"status":1,"count(status)":1},{"type":1,"status":2,"count(status)":1},{"type":2,"status":0,"count(status)":1}]} –  Mar 04 '20 at 21:50
  • @EmmanuelGabriel this is the format i want - { "status": "success", "code": 200, "data": { "1": { "0": 20, "1": 19, "2": 28 }, "2": { "0": 20, "1": 19, "2": 28 }, "3": { "0": 20, "1": 19, "2": 28 }, "4": { "0": 20, "1": 19, "2": 28 } } } –  Mar 04 '20 at 21:51
  • In other words, you would like to convert `data` from an array to an object? If so, then this is a possible duplicate of [this](https://stackoverflow.com/questions/4215737/convert-array-to-object). – Emmanuel Gabriel Mar 04 '20 at 21:56
  • @EmmanuelGabriel if you check question required and my output is different. Also type and status values are default and if no records it return o but my current output i only return types and status that have records in db –  Mar 04 '20 at 21:59
  • @EmmanuelGabriel please check '[Required Output]' and '[Output i return]' in the question –  Mar 04 '20 at 22:00

1 Answers1

0

So in handler you change:

const result = await Utils.getFeedbackStats(opts);

return { status: 'success', code: 200, data: result }

To

const result = await Utils.getFeedbackStats(opts);
const processedResult = processResult(result);

return { status: 'success', code: 200, data: processedResult }

Now processedResult takes data and returns data. It is a very simple algorithm that just shuffles the data. It is much easier to comprehend than async/await.

const processResult = ( { status, code, data } ) => {
    // This might be shorter to program
    const objResult = {
        "1": { "0": 0, "1": 0, "2": 0 },
        "2": { "0": 0, "1": 0, "2": 0 },
        "3": { "0": 0, "1": 0, "2": 0 },
        "4": { "0": 0, "1": 0, "2": 0 },
    };
    // augment default return
    return { 
      status, 
      code, 
      data: data.reduce((acc, { type, status, count }) => {
        return {...acc, [type]: {...acc[type], [status]: count } }; 
      }, objResult)
    };
};

// test 
const example = {
  "status":"success",
  "code":200,
  "data":[
      {
        "type":1,
        "status":0,
        "count":2
      },
      {
        "type":2,
        "status":0,
        "count":1
      },
      {
        "type":1,
        "status":1,
        "count":1
      },
      {
        "type":1,
        "status":2,
        "count":1
      }
   ]
};
console.log(processResult(example));
Sylwester
  • 47,942
  • 4
  • 47
  • 79