Retrieve the parent document information even when the subdocument array is filtered out

I have implemented the solution provided in this post How to filter array in subdocument with MongoDB

The method works correctly, except for cases where none of the elements in the array pass the test. In such situations, I end up with an empty array without any parent data.

SAMPLE DATA

 {
  "_id": "53712c7238b8d900008ef71c",
  "dealerName": "TestDealer",
  "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="611504121521150412154f020e0c">[email protected]</a>",
  "address": {..},
  "inventories": [
      {
          "title": "active",
          "vehicles": [
            {
              "_id": "53712fa138b8d900008ef720",
              "createdAt": "2014-05-12T20:08:00.000Z",
              "tags": [
                 "vehicle"
               ],
               "opts": {...},
               "listed": false,
               "disclosures": {...},
               "details": {...}
           },
           {
              "_id": "53712fa138b8d900008ef720",
              "createdAt": "2014-05-12T20:08:00.000Z",
              "tags": [...],
              "opts": {...},
              "listed": true,
              "disclosures": {...},
              "details": {...}
            }
         ]
     },
     {
         "title": "sold",
         "vehicles": []
     }
  ]
}

GOAL

My aim is to retrieve the top-level information (dealerName, email) of a user (document) and a property named vehicles containing all vehicles in the "active" inventory that have the property listed set to true.

CURRENT PROGRESS

This is the query I am using. (I utilize Mongoose but primarily rely on native Mongo features)

      {
        $match:
          email: params.username
      }
      {
        $unwind: '$inventories'
      }
      {
        $match:
          'inventories.title': 'active'
      }
      {
        $unwind:
          '$inventories.vehicles'
      }
      {
        $match:
          'inventories.vehicles.listed':
            $eq: true
      }
      {
        $group:
          _id: '$_id'
          dealerName:
            $first: '$dealerName'
          email:
            $first: '$email'
          address:
            $first: '$address'
          vehicles:
            $push: '$inventories.vehicles'
      }

ISSUE

Initially, I believed my query was correct, but when none of the vehicles are flagged as listed, the query returns an empty array. This outcome is expected due to

      {
        $match:
          'inventories.vehicles.listed':
            $eq: true
      }

not finding any matches, yet I still wish to obtain the dealerName and email

EXPECTED OUTPUT WHEN NO VEHICLES MATCH

[{"dealerName": "TestDealer", "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cebaabbdba8ebaabbdbae0ada1a3">[email protected]</a>", vehicles : []}]

ACTUAL RESULT

[]

Answer №1

To handle this situation, consider using $redact instead of $match. Here's an example:

db.collectionName.aggregate({
  $redact:{
    $cond:{ 
       if:{$and:[{$not:"$dealerName"},{$not:"$title"},{$eq:["$listed",false]}, 
       then: "$$PRUNE", 
       else: "$$DESCEND" 
    }
  }
})

In order to achieve the desired outcome, we need the first condition to avoid top level documents, the second condition to bypass second level ones, and the third one to handle vehicles that should be pruned. It's worth noting that there is no need for $unwind in this scenario!

Additionally, it is important to mention that $redact is only supported in version 2.6.

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

Is it possible to send array data in a jQuery AJAX call using the GET method?

Is there a way to pass a JavaScript array as a parameter in an AJAX GET request? I am currently dealing with an API call and have a method that requires three parameters, with the third one being an array. ...

Finding the top two numbers in an array Printout

I recently created a method called max2 that is designed to find and return the two highest values in an array. While I have been successful in finding the highest value, I am struggling to determine how to retrieve the second highest value. Below is the ...

What is the reason behind Angular's refusal to automatically bind data when an object is cloned from another object?

Check out this simple jsfiddle I made to demonstrate my question: fiddle Here is the HTML code snippet: <div ng-controller="MyCtrl"> <div ng-repeat="p in products"> <span ng-click="overwrite(p)">{{ p.id }}: {{ p.name }}& ...

Incapable of composing text using the MUI SearchBar

I'm having trouble with my Material UI search bar - it's not letting me type anything into it. How can I resolve this issue? Despite trying the suggested code snippets from other answers, I keep encountering errors when integrating them into my ...

Node.JS has deceived us with its false promises of `import` support

Could it be that I am making a mistake? I have been eagerly awaiting the experimental ES6 module loader in Node.JS since version 10. This feature is crucial for me to seamlessly use the same code in both the browser and node environments. This is how I w ...

What are the best methods for detecting devices in order to create customized CSS styles for iPad and Galaxy Tab?

Ensuring my web application is compatible with various devices is crucial. While I have created a common CSS for all mobile and tablet devices, it seems to be causing some problems specifically on the iPad. After finding a fix tailored for the iPad, I now ...

"PHP error: Accessing an undefined offset index 2

I'm currently working on a code snippet where I need to iterate through an array and replace specific characters within the 'color_codes' values. While the code is functioning correctly, I'm encountering an error message stating undefin ...

Transforming CSV CSS values with jQuery's CSS method: Step-by-step guide

My goal is to stack multiple background images within a single div container while ensuring their position is relative to the screen height. The problem I'm encountering is my inability to modify CSS values separated by commas. Here is my logical appr ...

NodeJS executes code within X minutes system design

How can I set up code to run at a flexible time? For instance, sending an HTTP request to an endpoint and modifying a database document after 60 minutes, with the ability to cancel it if another action occurs before that duration. What is the most effecti ...

Is there a specific jest matcher available for comparing Array<Objects>?

I'm currently testing the equality of two arrays of objects and have found that the toEqual matcher in Jest only works for arrays of strings. Is there another matcher available in Jest that can handle this condition? Please refrain from marking this a ...

Implementing asynchronous validation in Angular 2

Recently started working with Angular 2 and encountered an issue while trying to validate an email address from the server This is the form structure I have implemented: this.userform = this._formbuilder.group({ email: ['', [Validators.requir ...

I'm curious if there is a method in Vue.js that allows for creating a separator while utilizing v-for, much like the way `Array.join()` or FreeMarker's `<#sep>` functions operate

My goal is to create a list of <span> elements separated by commas using vue.js and v-for. Is there an easy way to achieve this in vue.js? In JavaScript, I would typically use users.join(", "). In FreeMarker templates, you can do some very interes ...

What's the issue with this HTML button not functioning properly?

I'm having an issue with a button in my code that is supposed to change the text from 'hello' to 'Goodbye', but for some reason, it's not working. I have ensured that my code is properly indented in my coding program. Below i ...

combine two integer arrays into a single character pointer in C

I have two arrays of integers, for example arr1={0,1,1,0,0} and arr2={1,0,1,1,1}. I am trying to concatenate the elements from both arrays into a single char* using malloc so that it looks like this: "01100,10111". I attempted to use a for loop for this ...

Confused about how to work with the Mongoose Model?

Currently delving into the world of MEAN stack development, my focus is currently centered on Mongoose in order to gain a deeper understanding. One question that continuously pops up in my mind is regarding the usage of models like the one below: var cam ...

What could be the reason behind needing to refresh my Express endpoint in order to access req.headers.cookies from the frontend?

I've encountered an issue where I must refresh my express endpoint in order to properly access req.headers.cookie. Without refreshing the endpoint, console.log(req.headers.cookie) returns undefined instead of the expected value. I have attached some i ...

Turn off auto-suggestion feature on the iPad and iPhone keyboard using JavaScript

I'm facing a challenge where I want to turn off the predictive suggestions and autocorrect feature on the iPad keyboard. This image is just for display purposes and not from my actual project. I need to hide the highlighted suggestion bar, and I am u ...

Step-by-step guide on how to have an AngularJS controller run continuously every 5 seconds once it has been initially called

My angular js file (app.js) contains the uuidCtrl controller, which triggers when called. When I want to call the controller 2 times, I have to load the page twice. However, I am looking for a solution to run it continuously after the first time it is call ...

The UI-Grid feature in Angular, when set to right-to-left (RTL) mode, incorrectly displays data in the opposite order compared to the

In my _Layout.cshtml file, I have a CSS that sets all UI controls to right-to-left direction using the following code: * { direction: rtl; } Currently, I am working with Angular's UI-Grid, and in RTL Localization, the ...

Disappearing Query Parameters in POST Requests with Node.js and Express

This is my first attempt at creating a JavaScript client and nodeJS server with Express that communicate using REST API. However, I'm running into an issue where any parameter I pass in the xhttp.send function is not being received on the back-end. O ...