Extract certain components from the aggregate pipeline depending on the presence of a particular field

This is a follow-up question to Draft an aggregate to group based on a nested attribute with lookup. Here are details about the two collections:

orders: [
  {
    "_id": "64355c928dcce8cdf4b9c7d2",
    "destinations": [
      {
        "ship_to_id": "64355c92af10d37993473e12",
        "sold_to_id": "64355c92a57d8b29412a1cc2",
        "type" : 1
      },
      ...
    ],
    "contact_details": [
      {
        "ship_to_ref": "aaa",
        "sold_to_ref": "bbb",
        "contact_email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3554755258545c591b565a58">[email protected]</a>" 
      },
      ...
    ]
  },
  ...
]
...

Answer №1

To optimize the aggregation process, consider inserting an additional step in the $filter function prior to executing the $unwind:

db.orders.aggregate([
  {$match: {contact_info: {$exists: true}}},
  {$project: {
      deliveries: {$filter: {
          input: "$destinations",
          condition: {$gte: ["$$this.type", 0]}
      }},
      destinations: 1,
      contact_info: 1
  }},
  {$unwind: "$deliveries"},
  {$group: {
      _id: {
        sold_to_id: "$deliveries.sold_to_id",
        ship_to_id: "$deliveries.ship_to_id"
      },
      contact_info: {$first: "$contact_info"},
      orders: {$push: {
          _id: "$_id",
          destinations: "$destinations"
      }}
  }},
  {$set: {locations: ["$_id.sold_to_id", "$_id.ship_to_id"]}},
  {$lookup: {
      from: "locations",
      localField: "locations",
      foreignField: "_id",
      as: "target_locations"
  }},
  {$project: {
      contact_info: 1,
      "_id.ship_to_id": "$_id.ship_to_id",
      "_id.sold_to_id": "$_id.sold_to_id",
      "_id.contact_email": "$contact_email",
      "_id.ship_to_ref": {$getField: {
          input: {$arrayElemAt: [
              "$target_locations",
              {$indexOfArray: ["$target_locations._id", "$_id.ship_to_id"]}
          ]},
          field: "reference_id"
      }},
      "_id.sold_to_ref": {$getField: {
          input: {$arrayElemAt: [
              "$target_locations",
              {$indexOfArray: ["$target_locations._id", "$_id.sold_to_id"]}
          ]},
          field: "reference_id"
      }},
      orders: 1
  }},
  {$set: {
      contact_info: "$$REMOVE",
      "_id.contact_email": {$getField: {
          input: {
            $first: {$filter: {
                input: "$contact_info",
                condition: {$and: [
                    {$eq: ["$$this.ship_to_ref", "_id.ship_to_ref"]},
                    {$eq: ["$$this.sold_to_ref", "_id.sold_to_ref"]}
                ]}
            }}
          },
          field: "contact_email"
      }}
  }}
])

Demonstrate the functionality using the example on the playground

Answer №2

Here is the updated query that successfully executed

db.indents.aggregate([
  {
    $project: {
      _id: 1,
      destinations: 1,
      contact_details: 1,
      contacts_gt_1: {
        $gt: [
          {
            $size: { 
             $cond: [ 
                { $isArray: "$contact_details" }, 
                "$contact_details", 
                []
             ]
            } 
          },
          0
        ]
      }
    }
  },
  {
    $match: {
      contacts_gt_1: true,
    }
  },
  {
    $project: {
      _id: 1,
      destinations: 1,
      contact_details: 1,
    }
  },
  {
    $unwind: "$destinations"
  },
  {
    $lookup: {
      from: "customers",
      localField: "destinations.sold_to_id",
      foreignField: "_id",
      as: "sold_to_ref"
    },
  },
  {
    $unwind: "$sold_to_ref"
  },
  {
    $lookup: {
      from: "customers",
      localField: "destinations.ship_to_id",
      foreignField: "_id",
      as: "ship_to_ref"
    }
  },
  {
    $unwind: "$ship_to_ref"
  },
  {
    $project: {
      _id: 1,
      destinations: 1,
      contact_details: 1,
      ship_to_ref: "$ship_to_ref.reference_id",
      sold_to_ref: "$sold_to_ref.reference_id",
    }
  },
  {
    $unwind: "$contact_details"
  },
  {
    $group: {
      _id: {
        ship_to_ref: "$contact_details.ship_to_ref",
        sold_to_ref: "$contact_details.sold_to_ref",
        contact_email: "$contact_details.contact_email",
      },
      orderData: {
        $addToSet: {
          _id: "$_id",
          destinations: "$destinations",  
        },
      },
    },
  },
  {
    $unwind: "$orderData"
  },
  {
    $group: {
      _id: {
        order_id: "$orderData._id",
        entry: "$_id",
      },
      destinations: {
        $push: "$orderData.destinations"
      },  
    }
  },
  {
    $group: {
      _id: "$_id.entry",
      orders: {
        $push: {
          order_id: "$_id.order_id",
          destinations: "$destinations"
        }
      }
    }
  },
])

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

What is the function of `function(data){}` in the context of JQuery's $.get

Within my MySQL database, there exists a column for VideoID and VideoCode In backend.php, I have crafted a PHP function with the goal of selecting the subsequent video from the list in the following manner: $VideoID = 0; function nextvideo(){ global ...

How to eliminate rows with images in Exceljs

I created a worksheet with an image in each row. However, when I filter or remove a row, the image for that row stays visible. I tested this on versions v4.4.0 and v4.3.0 I attempted various methods of adding images, but none of them seemed to work. Initi ...

Transforming an HTML Java script for compatibility with ASP.Net using C#

Hey there! I've been given the task of converting a page from HTML to aspx, and I'm happy to say that I've successfully completed it. However, my main challenge now is getting a javascript function to run when the submit button is clicked. ...

What is the best method to determine the cumulative time spent filling out a text box on a web page using Angular?

I am working on a web page that contains two text boxes. My goal is to track the total time spent inside each box when the user clicks the submit button at the end of the page. clickInside() { this.text = 'clicked inside'; this.wasIns ...

How can WebRTC be used to minimize latency between devices transmitting video streams?

Apologies for not including any code, but I am currently focused on expanding my knowledge of latency and webRTC. What methods are most effective in minimizing the latency between multiple devices sharing a video stream? Alternatively, how can we reduce l ...

Using a URL in an AJAX request

Before redirecting to another page, I am storing data from a textbox. When the user clicks the back button on the page load function in JavaScript, I retrieve the data from the textbox using: var pageval = $('#grid') .load('/Dealer/AllClai ...

Looking to showcase the current operating hours for today?

It would be great to feature a box on our upcoming library website showing the operating hours for that day. This way, visitors can easily see when the library is open each day they visit the site. Additionally, I plan to include a link for more extensive ...

Is there a way to enhance Backbone.Events within a Typescript ES6 Class?

Trying to incorporate Backbone's Events properties into a TypeScript class has hit a roadblock. Here's what I'm encountering... class Foo { constructor () { _.assign(this, Backbone.Events); // or _.extend() this.stopList ...

Error: An unexpected occurrence of an unknown provider: "$templateRequestProvider" was encountered, leading to issues with $templateRequest, $route, and the ngViewDirective

My angular app runs flawlessly on computer#1, but when I clone the git repo on computer#2 and run npm install, bower install, and grunt bower-install, things start to fail. After some research, it seems that the issue might be due to ng-route not being in ...

Issues with Formik sign-up

Working on a study project involving React, Typescript, Formik, and Firebase presents a challenge as the code is not functioning correctly. While authentication works well with user creation in Firebase, issues exist with redirection, form clearing, and da ...

What is the best way to automatically update templates in Django?

Let's say I have a simple model defined like this: class Text(models.Model): msg = models.TextField() The template I am using to render the data looks like: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8& ...

Chrome browser exhibits a phenomenon where the Bootstrap modal will erroneously print the same page multiple times based on the

When I open a modal, there's a print button inside it. I've researched solutions provided here and here to enable printing of Bootstrap modals, but I'm encountering a Chrome-specific bug. The issue doesn't occur in Safari, Firefox, or E ...

Utilizing jQuery boilerplate to execute functions

I am currently utilizing jQuery Boilerplate from However, I have encountered an issue where I am unable to call the "openOverlay" function within the "clickEvents" function. Oddly enough, I am able to successfully call "openOverlay" within the "init" fun ...

Creating asynchronous functions in Angular is a vital component to optimize performance and improve user

Within componentOne.ts, I am sending data via the sharedService like this: this.sharedService.sendData(this.getCheckedProduct); In componentTwo.ts, I am subscribing to the data in this manner: productList: any = []; getAllProducts: any = ...

Consider using React Components as an alternative to implementing pagination dots within Swiperjs, as it may help resolve the issue displaying

I seem to be encountering a small issue and I believe I am making a mistake somewhere. How can I replace the default dots with custom elements for pagination in Swiperjs for React? The custom element should return an SVG from an array of icons. Initially ...

Guide on redirecting a user to a different path when their token has expired

I am currently working on a project to create a simple website, and I am facing an issue with redirecting the user to a login page if their token has expired. I have attempted to solve this using React-JWT, but I am unsure of the proper way to do it. Here ...

What is the best way to choose $(this) within a JavaScript expression inside a template literal?

Is it possible to use template literals in the append method and get the index of the row generated? I understand that calling "this" inside the function selects the specified selector passed as an argument. $(document).on('click', '.ad ...

Methods to fix the error of "unspecified name" in Postman while accessing the Heroku URL with NodeJs and MongoDB

I'm navigating my way through Heroku, NodeJS, and MongoDB for the first time. I've set up a login form in Flutter with a backend in NodeJS and MongoDB. Utilizing Heroku to connect the backend to Flutter, however, when I try to access the URL (pro ...

Running client-side JavaScript code on the server side of an application

Currently, I am in the process of developing a web application that includes a web-based code editor specifically for JavaScript. The main goal of this project is to enable users to run JS code on the client side of the application with the use of server-s ...

Experiencing issues with integrating Vue.js into Spring MVC JSP pages

I am currently in the process of integrating views into my JSP files for my Spring MVC application. I have set up a very basic configuration, but I am encountering an issue where the message displayed from the 'msg' attribute in the data object a ...