Tips on modifying a Mongo Aggregation Query $group to store matching key in an object instead of having it as two separate items in $group

I have a query that aggregates data and produces results mostly as desired. However, I need to group only by branchId (not branchId and name) and organize the "name" values in an object along with their corresponding results.

Here is the schema:

  {
    process: { type: String, required: true },
    name: { type: String, required: true },
    error: { type: String },
    action: {
      type: String,
      required: true,
      enum: ['started', 'stopped', 'processing', 'completed', 'errored']
    },
    location: {
      branchId: { type: String }
    },
  },
  { timestamps: true }

This is the current aggregation query:

[
    {
        $match: {
            createdAt: { $gte: ISODate("2020-06-24T00:00:00.000+0000"), 
            $lte: ISODate("2020-06-25T00:00:00.000+0000") 
          }
        }
    },
    {
        $group: {
            _id: { branchId: '$location.branchId', name: '$name' },
            started: { $sum: { $cond: [{ $eq: ['$action', 'started'] }, 1, 0] } },
            processing: { $sum: { $cond: [{ $eq: ['$action', 'processing'] }, 1, 0] } },
            errored: {  $sum: {  $cond: [{ $eq: ['$action', 'errored'] }, 1, 0] } },
            completed: { $sum: { $cond: [{ $eq: ['$action', 'completed'] }, 1, 0] }
            }
        }
    },
]

CURRENT RESPONSE:

{ 
    "_id" : {
        "branchId" : "1", 
        "name" : "Product 1"
    }, 
    "started" : 1.0, 
    "processing" : 1.0, 
    "errored" : 0.0, 
    "completed" : 0.0
},
{ 
    "_id" : {
        "branchId" : "1", 
        "name" : "Product 2"
    }, 
    "started" : 1.0, 
    "processing" : 1.0, 
    "errored" : 1.0, 
    "completed" : 1.0
}

To achieve the DESIRED RESPONSE similar to the following, how can I modify the query?

{ 
    "_id" : "1",
    "product_1": {
        "started" : true,  
        "processing" : true, 
        "errored" : true, 
        "completed" : false
    },
    "product_2": {
        "started" : true, 
        "processing" : true, 
        "errored" : false, 
        "completed" : true
    }
},

I have set up a playground for testing: https://mongoplayground.net/p/zDaxC-SYtN4

Answer №1

To create an object based on the value of the document, utilize the $objectToArray operator.

{k:"hello", v:"world"}  --> {"hello":"world"}

Give this a try:

db.collection.aggregate([
  {
    $match: {}
  },
  {
    $group: {
      _id: "$location.branchId",
      data: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $replaceWith: {
      $arrayToObject: [
        {
          $concatArrays: [
            [
              { "k": "_id", "v": "$_id" }
            ],
            {
              $map: {
                input: "$data",
                in: {
                  k: "$$this.name",
                  v: {
                    started: { $eq: ["$$this.action","started"},
                    processing: { $eq: ["$$this.action","processing"]},
                    errored: { $eq: ["$$this.action","errored"]},
                    completed: {$eq: ["$$this.action","completed"]}
                  }
                }
              }
            }
          ]
        }
      ]
    }
  }
])

Try it out on MongoPlayground | Check out Alternative 3.4

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can you locate and emphasize specific text within various elements using JavaScript?

Created a script to highlight linked text in another HTML page. <p>Click <span class="f1"><a href="#myModal" data-reveal-id="myModal">here</a>/span></p> <div class="leftspread"> <p class="table-caption"& ...

Guide to automatically send a message when a new channel is added to a designated category using discord.js

Looking to develop a JavaScript Discord bot that automatically sends a message to new channels created under a designated category. The goal is to have the same message sent to every newly created channel. Seeking assistance from anyone knowledgeable on h ...

Issue with AngularJS expression not functioning as expected in Chrome for setting input type to "file"

I have encountered a strange bug while working on an Angular form builder application. The issue arises in Chrome when I try to dynamically set the input type based on a variable. Surprisingly, this method works perfectly for all input types except "file", ...

Is there a way to remove a file that is currently being used by a read stream?

I am facing an issue where I cannot delete a folder after making a POST request because it is still in use by a read stream. Despite trying to use .destroy(); and .unpipe();, the folder remains in use. The only way I can delete files is by closing my Node. ...

The Node.js Express server fails to retrieve data after a certain period of time

There is a problem with one specific route on the server, as it is returning a 404 error while all other routes are functioning properly. The route starts working and then suddenly stops without any clear reason. Here is the error message that I am receiv ...

JavaScript code for extracting the value of a specific table cell from the provided screenshot

Looking at the image below, as someone new to JavaScript development, I have two questions. First, how can I directly retrieve the value of the second td from $('#cart-subtotal-order.total.subtotal td') in JavaScript code? Secondly, I need to kno ...

Nested for loops utilized to organize items

I'm struggling with implementing a nested for loop to sort items in an array. Unfortunately, I'm encountering an issue where some values are being duplicated and I can't seem to identify the root cause of the problem. My logical reasoning sk ...

Conceal a dataLabel for a particular series in Highcharts

Currently, I am dealing with a chart that consists of 5 series - one as columns and the other four as lines with constant values. My dilemma lies in wanting to display dataLabels for only one of those series. Despite my efforts to activate/deactivate dataL ...

Issue with HighCharts Series Data Points Not Being Added

I am currently facing a major challenge in dynamically changing data for highcharts based on date. To provide context for my project, it involves logging system data with timestamps. I have implemented a date and time picker to specify the start and end da ...

When submitting, Redux objects are being submitted with empty values

Whenever I try to submit my form, the object is being submitted empty. This was confirmed using the redux dev-tool, where it shows that the object is empty upon submission. The expected behavior is for a card to appear on the DOM with the information enter ...

Tips for deleting the displayed URL during a web page print in PHP

Is there a way to remove the URL from a page when printing using PHP? I want to achieve this without requiring my clients to change their browser settings. Any assistance would be greatly appreciated! ...

Tips for displaying a loading spinner each time the material table is loading

Hey there, I'm currently working on an Angular project where I need to display a table using Material Table. To indicate that the table is loading, I've defined a variable called isLoading. Here's how it works: In my TypeScript file: @Com ...

Sending Data Through Button from navBar in React-Native-Router-Flux

I have been working on a project that utilizes `react-native-router-flux` and I am facing a challenge in passing an object through `props`. Typically, I would use `Actions.someKey({ someProp: object })` for navigation. However, in this case, I need to navi ...

Enforce file selection using AngularJS based on certain conditions

When data is received from the backend in JSON format, it looks like this: { "data":{ "xyz":[ { "number":"1", "short_text":"Sign Contract", "long_text":"Enter names after contract signing", "is_photo":false ...

Converting datetime.date into JSON using JavaScript's Date serializer

Is there a way to convert a Python list of datetime.date objects into a JSON array of JavaScript Date objects? For instance: lst = [datetime.date(2013, 12, 30), datetime.date(2013, 12, 31)] print serialize(lst) # should print "[new Date(2013, 12, 30), new ...

Utilize eventRender with fullCalendar 4 and React to enhance event rendering

When using fullCalendar in jQuery, I utilized the eventRender function like this: eventRender: function (event, element, view) { if (event.finito == 0) { element.css('background-color', '#FF0000'); } }, Now, I am a ...

Tips on utilizing the event.preventDefault() method within AngularJS?

Recently, I stumbled upon a technique to prevent page refreshing after submitting a form by using event.preventDefault();. As someone who is still learning Angular, I am unsure of how to incorporate this syntax into my Angular controller. Is "event" some s ...

The node find method is acting up and only returning partial data from the mongodb collection

In the process of creating a backend for a Twitter-like application, I encountered an issue when attempting to retrieve all users along with their information. The problematic code snippet is as follows: router.get("/tweets", (req, res) => { User.fi ...

jquery mobile page navigation option

I am a big fan of the navigation system in jQuery Mobile: <a href="page-transitions-page.html" data-transition="slidedown" class="ui-btn ui-corner-all ui-shadow ui-btn-inline">page</a> () It is incredibly user-friendly, and I really enjoy th ...

Error: Collection2 validation did not pass: The field 'name' must be filled in, the field 'email' cannot be empty, and the field 'message' is mandatory

I need to set up a way for visitors to send messages through my website const mongoose = require("mongoose"); mongoose.connect("MongoDb-Connection-Uri") .then(() => { console.log("mongodb connected"); }) .catch(() => { console.log("fail ...