Leveraging conditions to retrieve information in the desired format from MongoDb

Here is an example of what the sample documents look like

{
    userId: 1,
    totalGames: 10,
    winStats: 4,
    lostStats: 6,
    g1Stats: {
      totalGames: 4,
      winStats: 1,
      lostStats: 3,
    },
    g2Stats: {
      totalGames: 5,
      winStats: 2,
      lostStats: 3,
    },
    g3Stats: {
      totalGames: 1,
      winStats: 1,
      lostStats: 0,
    }    
}

The data will be returned in this format

{
  userId
  totalGames
  winStats 
  lostStats
}

If the gameType parameter includes [g1, g2], the result will be

{
  userId: 1,
  totalGames: 9,
  winStats: 3,
  lostStats: 6
}

which is the sum of g1Stats and g2Stats

If the gameType is empty, the query should return

{
 userId: 1,
 totalGames: 10,
 winStats: 4,
 lostStats: 6
}

Could someone assist me with constructing this query? Please note: Sorting operations are being performed on these fields which is why this specific format is used.

Answer №1

Below is a strategy to achieve this objective:

db.collection.aggregate([
  {
    "$project": {
      userId: 1,
      totalGames: {
        "$cond": {
          "if": {
            "$eq": [
              {
                "$size": {
                  "$concatArrays": [
                    [
                      "g1Stats",
                      "g2Stats"
                    ]
                  ]
                }
              },
              0
            ]
          },
          "then": "$$ROOT.totalGames",
          "else": {
            "$reduce": {
              "input": [
                "g1Stats",
                "g2Stats"
              ],
              "initialValue": 0,
              "in": {
                "$sum": [
                  "$$value",
                  {
                    "$function": {
                      "body": "function(key, doc) {  return doc[key].totalGames }",
                      "args": [
                        "$$this",
                        "$$ROOT"
                      ],
                      "lang": "js"
                    },
                    
                  }
                ]
              }
            }
          }
        }
      },
      winStats: {
        "$cond": {
          "if": {
            "$eq": [
              {
                "$size": {
                  "$concatArrays": [
                    [
                      "g1Stats",
                      "g2Stats"
                    ]
                  ]
                }
              },
              0
            ]
          },
          "then": "$$ROOT.winStats",
          "else": {
            "$reduce": {
              "input": [
                "g1Stats",
                "g2Stats"
              ],
              "initialValue": 0,
              "in": {
                "$sum": [
                  "$$value",
                  {
                    "$function": {
                      "body": "function(key, doc) {  return doc[key].winStats }",
                      "args": [
                        "$$this",
                        "$$ROOT"
                      ],
                      "lang": "js"
                    },
                    
                  }
                ]
              }
            }
          }
        }
      },
      lostStats: {
        "$cond": {
          "if": {
            "$eq": [
              {
                "$size": {
                  "$concatArrays": [
                    [
                      "g1Stats",
                      "g2Stats"
                    ]
                  ]
                }
              },
              0
            ]
          },
          "then": "$$ROOT.lostStats",
          "else": {
            "$reduce": {
              "input": [
                "g1Stats",
                "g2Stats"
              ],
              "initialValue": 0,
              "in": {
                "$sum": [
                  "$$value",
                  {
                    "$function": {
                      "body": "function(key, doc) {  return doc[key].lostStats }",
                      "args": [
                        "$$this",
                        "$$ROOT"
                      ],
                      "lang": "js"
                    },
                    
                  }
                ]
              }
            }
          }
        }
      }
    }
  }
])

Check out the demo link. The approach utilizes $cond to determine if the game type array is empty; if so, it retrieves the value for a key at the top level, otherwise employing $reduce, $sum, and $function to calculate the desired outcomes.

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

Issue with VueJS: Child method not getting executed when passed to parent

Within this context, the parent element is transmitting the name and age props to the child component. The child then emits a customized event called changeAgeFn which transfers its changeAge method back to the parent. In the parent component, the passed ...

Vuex getters not displaying expected values in computed properties until entire page has finished loading

When working with computed properties using data fetched by the mapGetters function in my Vuex store, I always encounter the issue of getting an undefined value until the entire page or DOM is fully loaded. For instance, I have an example of an isRegister ...

Overflow of Primary Text in Material UI List Item

I apologize if this question has already been asked, but I have searched and couldn't find the solution! I am facing an issue with a Material UI listview that has a fixed width within a sidebar. The titles of some options are not properly rendering a ...

Exploring the capabilities of Vue.js, including the use of Vue.set()

Just starting out with Vuejs and I have a query regarding the correct approach to achieve what I want. My Objective I aim to have some dates stored in an array and be able to update them upon an event trigger. Initially, I attempted using Vue.set, which ...

Remove the model from operation

I'm fairly new to angularjs and have a working service. However, I want to move the patient model out of the service and into a separate javascript file. I believe I need to use a factory or service for this task, but I'm not entirely sure how to ...

Preventing unauthorized access to files in ExpressJS public directories

Is there a way to conceal files served by the Node server? Despite my attempts to redirect certain files and directories, Express 4.X does not seem to cooperate. I have also experimented with sending 4XX HTTP responses when specific files are requested, bu ...

Sharing stickers with Discord.js version 13

I have encountered an issue while trying to forward messages sent to my bot via DM. Everything is functioning smoothly, except for sending stickers. Whenever I attempt to send a message with a sticker, an Error DiscordAPIError: Cannot use this sticker is ...

a service that utilizes $http to communicate with controllers

My situation involves multiple controllers that rely on my custom service which uses $http. To tackle this issue, I implemented the following solution: .service('getDB', function($http){ return { fn: function(){ return $http({ ...

What are the different scenarios in AngularJS where $scope is utilized versus when var is utilized?

Which is more efficient in AngularJS: using var or $scope. for variables inside functions? I am asking this question because I recently came across information about $watch, $digest, and $apply in AngularJS. While I may not have fully grasped the concept ...

Send both queries using JSON

I am trying to pass company information using Json, and I also want to pass the areas using the same method. However, I am encountering some issues. Can anyone provide assistance? if($_GET['method']=="get_all_companies"){ $query = "SELECT co ...

Using jQuery to Save Data Locally in a JSON File

Just a heads up; all of my work is kept local. I've been on the hunt for ways to write to a JSON file from a JS script using jQuery. Many methods involve PHP, but I don't have much experience with that language and would prefer to avoid it for no ...

Highlight the navigation transition in the menu

Is there a more updated tutorial available for creating an underline effect that slides from one link to another when hovered over and remains at the clicked link? I have come across a tutorial on Underline transition in menu which seems to be based on th ...

What causes a 400 Bad Request error when attempting to send data using jQuery Ajax within the Spring framework

I am facing an issue with submitting JSON data through jQuery AJAX. I have searched for similar problems online, but none of the solutions seem to be working for me. $.ajax({ type : "POST", contentType : "applic ...

Guide on integrating React with Node.js and HTML

I've tried various methods, searched on Google, and checked the official site, but nothing seems to work. The code only functions properly when I include it in the HTML file of node.js like this: <!DOCTYPE html> <html lang="en"& ...

How to Identify and Print a Specific Property in a JSON Object using Node.js?

Hey there, I'm having trouble extracting the trackName from the JSON object provided here. I've tried accessing it using this code: console.log(res.text.results[0].trackName); but unfortunately, I keep getting this error message: TypeError: Cann ...

Testing the functionality of an Express Rest API with Mocha unit tests

I have just started diving into the world of unit testing. While I've been successful in running simple tests such as "adding two numbers and checking if the result is greater than 0", my goal now is to develop a REST API using Test-Driven Development ...

Retrieve the accurate placeholder color using JavaScript

I modified the default placeholder color of my input to blue. How come I am seeing a black placeholder color when using JavaScript? const fetchPlaceholderColor = () => { let inputElement = document.querySelector('.myClass'); let inputEl ...

Is there a way to refresh CSS styles when the window width is adjusted?

Is there a way to refresh CSS styles when the window width changes? I attempted this method, but unfortunately it did not work as expected. A simple refresh (F5) helps to rectify the CSS tags. jQuery(function($){ var windowWidth = $(window).width(); ...

The evaluation of jQuery did not function properly on the less.css file

I have a jQuery function that I am using as shown below @winheight:`$(window).height()` within my less file. However, when I compile it to CSS, I encounter a compiler error I am currently using a software called Crunch Compiler Errors You are usin ...

Managing Emitted Events in Vue.js Components within Components: A Guide

I have created a Toolbar Item component as follows: <template> <div class="flex cursor-pointer items-center justify-center rounded-full border-2 border-gray-300 p-1 shadow-sm transition-all duration-300 hover:scale-110 hover:bg-black ho ...