Incorporating a $match query in MongoDB aggregation with lookup

When retrieving data from 2 collections, I aim to establish a connection between the two based on the MongoDB playground. Specifically, while extracting information from the second collection, I seek to filter results by matching a specific tag.

This is the query I have formulated:

db.Vote.aggregate([
    {
        $match: {
            comment: {
                $ne: null,
            },
            "comment.topic": {
                $exists: 1,
                $regex: ".",
                $options: "i",
            },
        },
    },
    {
        $group: {
            _id: {
                topic: "$comment.topic",
                text_sentiment: "$comment.text_sentiment",
            },
            total: {
                $sum: 1,
            },
            postIds: {
                $push: "$postId",
            },
        },
    },
    {
        $group: {
            _id: "$_id.topic",
            total: {
                $sum: "$total",
            },
            text_sentiments: {
                $push: {
                    k: "$_id.text_sentiment",
                    v: "$total",
                },
            },
            postIds: {
                $push: "$postIds",
            },
        },
    },
    {
        $project: {
            topic: "$_id",
            topicOccurance: "$total",
            sentiment: {
                $arrayToObject: "$text_sentiments",
            },
            postIds: {
                $reduce: {
                    input: "$postIds",
                    initialValue: [],
                    in: {
                        $concatArrays: ["$$value", "$$this"],
                    },
                },
            },
        },
    },
    {
        $sort: {
            topicOccurance: -1,
        },
    },
    {
        $lookup: {
            from: "Post",
            localField: "postIds",
            foreignField: "_id",
            as: "tag",
        },
    },
    {
        $addFields: {
            postIds: {
                $setUnion: "$postIds",
            },
            tag: {
                $setUnion: {
                    $map: {
                        input: "$tag",
                        in: "$$this.tag",
                    },
                },
            },
        },
    },
]);

The resulting output resembles this:

{
    "_id" : "Collaboration & Teamwork",
    "topic" : "Collaboration & Teamwork",
    "topicOccurance" : 355,
    "sentiment" : {
        "Negative" : 102,
        "Neutral" : 132,
        "Positive" : 121
    },
    "postIds" : [
        "0iWc2U8FVz",
        "3Qzysi2cXD",
        "3hRx7qAvcb",
        "BsrTDkHmkE",
        "LT2HE2uEa5",
        "Qw0WcUBcnY",
        "U72zss2Af5",
        "V9DcRcSawi",
        "hNwFVJ2bBk"
    ],
    "tag" : [
        [
            "Engagement"
        ],
        [
            "Environment"
        ],
        [
            "Feedback & Recognition"
        ],
        [
            "Leadership"
        ],
        [
            "Management"
        ],
        [
            "Meaningful Work"
        ],
        [
            "Open Text"
        ]
    ],
    "totalDocs" : 39
}

Following the tag match, only Posts with a specific tag = foo will be included in the response. How can this be achieved?

Explore the Mongo DB Playground for the query and sample data.

Answer №1

Kindly insert the following code snippet into the lookup section to enhance its functionality

{
      $lookup:
         {
           from: "Post",
           let: { tagInit: "$tag", postidInit: "$postIds" },
           pipeline: [
              { $match:
                 { $expr:
                    { $and:
                       [
                         { $eq: [ "$_id",  "$$postids" ] },
                         { $eq: [ "$tag", "$$tagInit" ] }
                       ]
                    }
                 }
              }
           ],
           as: "tag"
         }
    }

Answer №2

Update: To retrieve the sentiment and postIds that match the tag criteria in a query, you can employ the $lookup at an earlier stage.

db.Vote.aggregate([
  {$match: {"comment": {$ne: null},
      "comment.topic": {$exists: 1, $regex: ".", $options: "i"}}
  },
  {$lookup: {
      from: "Post",
      let: {postId: "$postId"},
      pipeline: [
        {$match: {$expr: {$and: [{$eq: ["$_id", "$$postId"]}, {$in: ["a", "$tag"]}]}}}
      ],
      as: "tag"
    }
  },
  {$match: {$expr: {$gt: [{$size: "$tag"}, 0]}}},
  {$group: {
      _id: {topic: "$comment.topic", text_sentiment: "$comment.text_sentiment"},
      total: {$sum: 1}, postIds: {$push: "$postId"}}
  },
  {$group: {
      _id: "$_id.topic",
      total: {$sum: "$total"},
      text_sentiments: {
        $push: {k: "$_id.text_sentiment", v: "$total"}},
      postIds: {$push: "$postIds"}
    }
  },
  {$project: {
      topic: "$_id",
      topicOccurance: "$total",
      sentiment: {$arrayToObject: "$text_sentiments"},
      postIds: {
        $reduce: {
          input: "$postIds",
          initialValue: [],
          in: {$concatArrays: ["$$value", "$$this"]}
        }
      }
    }
  },
  {$sort: {"topicOccurance": -1}},
  {$addFields: {postIds: {$setUnion: "$postIds"},
      tag: {$setUnion: {$map: {input: "$tag", in: "$$this.tag"}}
      }
    }
  }
])

View the demonstration on the playground sample

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

Sharing controller methods in Angular.js is a key aspect of enhancing

In my current project, I originally used Knockout for the CMS functionality, but decided to switch to Angular because I preferred its features. One of the key sections in the CMS is dedicated to 'Users', featuring a table where headers can be cli ...

Designing architecture for NPM packages in TypeScript

I am currently developing multiple NPM packages using TypeScript and I am exploring the most effective strategies for supporting various target architectures. When compiling to ES3, there is extensive support but it comes with additional boilerplate for c ...

Limiting Velocity in a Two-Dimensional Spacecraft

Like many others diving into the world of programming, I decided to challenge myself with a spaceship game project. At this point, I have successfully incorporated parallax stars and other essential features expected in a space-themed game. The spacecraft ...

Error: Unable to locate App.js file upon transition to Typescript

I'm in a bit of a bind with my Laravel project and I'm struggling to find a solution. I recently tried to upgrade from vue2 to vue3 with typescript, following this tutorial for the vue upgrade and this tutorial for typescript integration. However ...

Including a JavaScript library in a Maven project with JSF

Currently, I am working on a JSF project with Maven and I am utilizing a JavaScript library for developing a 3D graphics interface. I am looking for a way to add/import this JS library into my project without the need to manually move/copy all the JS files ...

"Transmitting an ajax POST call and receiving a corresponding GET response

Currently, I am utilizing the following AJAX code: $.ajax({ url: "Editor.aspx/Page_LoadComplete", data: { "contentCheckCode": contents }, type: "POST", success: function (response) { alert("Contents saved..."); }, error: fu ...

Guide to setting up a back button to return to the previous page in an iframe application on Facebook

I've developed a Facebook application that is contained within an IFRAME. Upon opening the application, users are presented with the main site, and by clicking on the gallery, they can view a variety of products. The gallery includes subpages that lo ...

The node module for converting JSON to XML is having trouble properly parsing the data into the desired structure

I'm currently working on converting a JSON object to XML in my Node.js service using the jstoxml module. Here is the input structure I am dealing with: { "user": "505723c5750c1fa2177682ed", "uri": "http://localhost:3000/users/505723c5750c1fa2 ...

the session data is being mishandled

I have integrated express-session and express-mysql-session in my application to handle sessions and store them in a MySQL database. The session data is saved in a table named "sessions". const express = require('express'); const session = requir ...

You cannot apply the "delete" operator to outcomes of a mongoose query

Having trouble removing a key from my data before sending it to the browser. It seems that simply deleting it doesn't work when dealing with a mongoose object: delete myObject.property When I use console.log(delete myObject.property) it returns true ...

Tips for implementing a checkbox (with tick/untick functionality) as a replacement for a plus/minus toggle using HTML

Is it possible to use checkboxes instead of plus and minus signs for expanding and collapsing sections? Can the plus and minus symbols be incorporated into the checkbox itself, so that clicking on the checkbox toggles between plus and minus states? Any hel ...

Exploring Data Points Through Mongodb Queries

I am attempting to retrieve specific information from my database based on a type score that is less than 70 and has the type exam. Here is an example of the data structure I am working with: {"_id":0,"name":"aimee Zank", "scores":[{"score":1.46317973670 ...

Typescript inheritance results in an undefined value being returned

I am trying to understand the code below, as I am confused about its functionality. In languages like C# or Java, using the base or super keyword usually returns values, whereas in TypeScript, I am receiving "undefined". However, when I switch from using " ...

Creating an optional item in a fixed array of Promises with Typescript

I am encountering an issue with a variable called promises. Here is what it looks like: const promises: | [Promise<boolean>, Promise<boolean>] | [Promise<boolean>, Promise<boolean>, Promise<{ currency: str ...

Chaining inheritance through Object.create

Recently, I decided to experiment with Object.create() instead of using new. How can I achieve multiple inheritance in JavaScript, for example classA -> classA's parent -> classA's parent's parent, and so on? For instance: var test = ...

What is the best way to implement multiple preload scripts for various Electron windows when utilizing electron forge with the webpack template?

I am utilizing the typescript+webpack template provided by electron forge. To load a single preload script with webpack, I need to set the constant called MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY in the package.json file. This constant can be configured like thi ...

Upon mounting, the componentDidMount function and XMLHttpRequest retrieved data redundantly due to an invalid JSON format

I'm currently utilizing a basic express static server to efficiently manage my static files. app.use(express.static(path.join(__dirname, 'public'))); Presented below is the webpack.config.js file const webpack = require('webpack&apos ...

Display validation in HTML5 only when the form is submitted

Here is the code snippet I am referring to: <input required pattern="[0-9]{5,10}" oninput="setCustomValidity('')" oninvalid="setCustomValidity('Type something')" /> I'm looking for a way to remove o ...

Results from AWS DynamoDB Scan operation

I am currently utilizing the AWS JavaScript SDK for DynamoDB, and executing a scan operation to retrieve a list of items from a table. The returned results show that each value is enclosed within an attribute type key: For instance: An anticipated result ...

The particles-js effect only partially fills the page

I've encountered some issues with particles-js. Firstly, it fails to cover the entire page. Additionally, I seem to be unable to interact with the particles for reasons unknown. Here is the HTML code snippet: <script type="text/javascript" src="j ...