MongoDB's conditional aggregation function allows users to manipulate and aggregate data based

My mongodb contains data like this:

{
  "_id": "a",
  "reply": "<",
  "criterion": "story"
},
{
  "_id": "b",
  "reply": "<",
  "criterion": "story"
},
{
  "_id": "c",
  "reply": ">",
  "criterion": "story"
}

What I need is the following result:

 {
   "criterion": "story",
   "result" : {
                ">" : 1,
                "<" : 2
              } 
 }

I intend to perform an aggregation based on "criterion". While this would result in 1 document, I actually want to track the occurrences of "<" and ">" and store that information in a new key as shown in the JSON above. This is the underlying logic behind my requirement. Can anyone with strong knowledge in mongodb assist me with this?

Answer №1

To achieve the desired result, utilizing the aggregation framework is necessary. This involves running an aggregation pipeline that incorporates a $group operator pipeline stage. This stage aggregates the documents to generate the desired counts by using the accumulator operator $sum.

In order to create independent count fields, a ternary operator such as $cond is essential. This operator facilitates the evaluation of counts based on the value of the "reply" field. Based on a logical condition, the $cond operator assigns a value of 1 or 0, translating boolean results into numerical values to be fed into the $sum expression:

"$cond": [
    { "$eq": ["$reply", ">"] },
    1, 0
]

When processing a document, if the "reply" field contains a ">", the $cond operator assigns a value of 1 to $sum. Otherwise, it sums up zero.

For the final step in the pipeline, utilize the $project operator. This step allows for reshaping each document in the stream, including/excluding fields, renaming fields, injecting computed values, and more, similar to the SQL SELECT statement.

The following pipeline executes the desired outcome:

Model.aggregate([
    {
        "$group": {
            "_id": "$criterion",
            ">": {
                "$sum": {
                    "$cond": [ 
                        { "$eq": [ "$reply", ">" ] }, 
                        1, 0 
                    ]
                }
            },
            "<": {
                "$sum": {
                    "$cond": [ 
                        { "$eq": [ "$reply", "<" ] }, 
                        1, 0 
                    ]
                }
            }
        }
    },
    {
        "$project": {
            "_id": 0,
            "criterion": "$_id",
            "result.>": "$>",
            "result.<": "$<"
        }
    }
]).exec(function(err, result) {
    console.log(JSON.stringify(result, null, 4));
});

Sample Console Output

{
    "criterion" : "story",
    "result" : {
        ">" : 1,
        "<" : 2
    }
}

Note: This method assumes fixed values for the $reply field. If the values are dynamic or unknown, this approach may not be flexible.


For a more efficient and flexible alternative that handles unknown count field values, consider using the following pipeline:

Model.aggregate([
    { 
        "$group": {
            "_id": {
                "criterion": "$criterion",
                "reply": "$reply"
            },
            "count": { "$sum": 1 }
        }
    },
    { 
        "$group": {
            "_id": "$_id.criterion",
            "result": {
                "$push": {
                    "reply": "$_id.reply",
                    "count": "$count"
                }
            }
        }
    }
]).exec(function(err, result) {
    console.log(JSON.stringify(result, null, 4));
});

Sample Console Output

{
    "_id" : "story",
    "result" : [ 
        {
            "reply" : "<",
            "count" : 2
        }, 
        {
            "reply" : ">",
            "count" : 1
        }
    ]
}

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

Guide on updating the default screen background color for all pages in React JS (Next JS) with the help of tailwind CSS

How can I change the default screen background color for all pages within my web application? Here are the technologies I've used: React JS Next JS Tailwind CSS I would like to set the screen background color of all pages to a light grey shade, as ...

Splitting jQuery - discover and distribute all price categories

I am faced with a challenge on my page where I have a list of items each displaying prices in GBP. The price is enclosed within a span element with a class of "price". My goal is to change the value of all the prices by dividing them by 1.2. Here's an ...

jQuery UI - Inconsistent results with multiple autocomplete feature

I am facing an issue with the tags.json file provided below: [ {"label" : "Aragorn"}, {"label" : "Arwen"}, {"label" : "Bilbo Baggins"}, {"label" : "Boromir"} ] In addition, I have a JavaScript code snippet (which ...

Confirmation checkbox that retains original value if canceled

Imagine a scenario where there is a checkbox value. When the checkbox value changes, the user is asked, "Do you want to SHOW this item on the website?" or "Do you want to HIDE this item on the website?" Everything seems to be working fine, except for one ...

Running JavaScript code for the iframe

Question about Manipulating Content in an iFrame: Invoking javascript in iframe from parent page I am attempting to load a HTML page with an iFramed website and then manipulate the content by removing an element, referred to as '#test'. < ...

What is the best way to extract a JSON object from a website search using getJSON or similar techniques?

Can anyone provide guidance on utilizing .getJSON() to access JSON-encoded information from a website that is being searched? I've implemented a Google Custom Search API for my site with the aim of retrieving the JSON file from the search results. Fo ...

How to display a modal within a router-link in Vue 3?

Below are buttons with router-links. However, I only want the calculator button to open a modal. When I execute the code provided, all buttons trigger the modal instead of just the calculator button. Output: https://i.sstatic.net/layQ1.png Router-link C ...

Experiencing difficulty in updating GitHub pages with React application

Looking for help updating my deployed active react app on GitHub pages with newer code, such as color changes and text updates. The updated code has been pushed to the main branch of my GitHub repo but the live GitHub page is not reflecting the changes. De ...

What is the reason for having to add my IP to the white-list daily?

As a beginner, I am delving into the world of back-end development with Node.js, Express.js, and Mongoose for educational purposes. My database is hosted on Atlas-Mongo DB. Initially, everything seemed to be running smoothly as I configured it with the fre ...

Transforming JSON into array format with key-value pairs using JavaScript

Currently, I am working on a web application that is receiving data in a specific format from a node server: "{""elements":[{"10sr2b2":{"total":0,"bad":22,"clients":["fc8e7f","fc8e7e"],"zone":"101900"}}]}" The issue lies in the fact that this data is str ...

What is the process for encrypting data with javascript and decrypting it with php?

Looking for a way to encrypt data with a JavaScript function to use in a URL passed through an ajax GET request? For example, you could have encrypted data like TDjsavbuydksabjcbhgy which is equivalent to 12345: http://sample.com/mypage/TDjsavbuydksabjcbh ...

Error message triggered by Yubikey in WebAuthn Authentication API

Having trouble with implementing WebAuthn support on a new website, specifically encountering issues during the navigator.credentials.get() call. The client browser being used is Firefox 85.0 on Fedora 33, and the server is Apache httpd also on Fedora 33. ...

How can I assign the items in a list as keys to an object in redux?

I am currently utilizing Redux in combination with Reactjs. The Redux Documentation states: It's recommended to return new state objects instead of mutating the existing state. My current object's state looks like this: state = [..., {id: 6 ...

What is the best way to trigger a function on every navigation event in a React Native application?

Here is my scenario: We are currently working on adding an inactivity timeout feature to a react native app. The goal is to have the timeout reset every time a user interacts with the app or navigates between screens. At the moment, we have a callback fu ...

Using vuex to paginate through firestore data and seamlessly update the state with new information

After taking advice from Tony O'Hagan on Stack Overflow, I integrated the following code to exhibit a paginated query: bindUsers: firestoreAction(({ bindFirestoreRef }) => { return bindFirestoreRef('users', Firebase.firestore().c ...

Managing a single repository with multiple packages using npm

Currently, I am in the process of developing a node.js application that requires scalability and maintainability. The concept revolves around having a single repository with multiple modules embedded within it. We have opted to utilize local modules with ...

I need help figuring out how to represent a nested array within an array of objects within my data instance in Vue

Currently, I have a loop that is showcasing a list of items along with their respective sub-items. The data response payload for this operation appears like the following. I have successfully executed the loop and managed to display it on my frontend desi ...

Exploring client-server relationships within the Express framework

Is there a way to transfer an object to JavaScript on the client side? I previously asked this question and received an answer, but because I was unable to check it on my computer, I accepted the response. You can view the details here: Client receive jso ...

Serving files from a Node.js server and allowing users to download them in their browser

I am facing an issue with my file repository. When I access it through the browser, the file automatically downloads, which is fine. However, I want to make a request to my server and then serve the file result in the browser. Below is an example of the GE ...

Is there a way to check for invalid string literals within a string?

Looking for a way to test for invalid (unclosed) strings within a given string? This regex might help: /"[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]* ...