Search for two specific values using Mongoose's find() function and retrieve only the documents that fit both criteria

After thorough research, I have not been able to find a precise solution to my issue. Despite going through the Mongoose documentation and attempting various approaches, as a newcomer to MongoDB, I am eager to create my own API following numerous tutorials.

The Objective:

To execute a GET request to

http://localhost:3000/seasons/19/1
and retrieve the details of series 19 along with the selected episode 1

Something similar to:

{
        "_id": "5b893aff76c12c166c4e75ae",
        "season_number": 19,
        "name": "Season 19",
        "number_of_episodes": 24,
        "episode": [
            {
                "_id": "5b895e56089a9a152c16af1f",
                "episode_number": 1,
                "name": "19.01",
                "length": "1:23:33",
                "author": "Aaron Wright",
                "release": "2018-01-13T00:00:00.000Z",
                "description": "We kick off our 2018 season with the worst of CES and the future of smart toilets before Aaron unravels the controversial “Dear David” saga that has sparked controversy. We then look at state sponsored mind control programs and the hypnotic experiments performed on unwitting Princeton students in the 1960s."
            },

}

The Challenge:

I am struggling to devise a method to return the object as shown above with just the single selected episode. While all the data is present in episodes, I can fetch it by manually using episodes[0] etc.

For those interested, here is the repository file to avoid prolonging this post: https://github.com/DannnB/mysterious-universe-api/blob/master/api/controllers/seasons.js

  • Line: 63
  • Name: seasons_get_episode_number

Appreciate any assistance provided!

The database - hosted on MongoDB Atlas - operating on the free tier thus unable to utilize $where and opting against its usage due to its resource-intensive nature.

 "data": [
    {
        "_id": "5b893aff76c12c166c4e75ae",
        "season_number": 19,
        "name": "Season 19",
        "number_of_episodes": 24,
        "episodes": [
            {
                "_id": "5b895e56089a9a152c16af1f",
                "episode_number": 1,
                "name": "19.01",
                "length": "1:23:33",
                "author": "Aaron Wright",
                "release": "2018-01-13T00:00:00.000Z",
                "description": "We kick off our 2018 season with the worst of CES and the future of smart toilets before Aaron unravels the controversial “Dear David” saga that has sparked controversy. We then look at state sponsored mind control programs and the hypnotic experiments performed on unwitting Princeton students in the 1960s."
            },
            {
                "_id": "5b895fee089a9a152c16af20",
                "episode_number": 2,
                "name": "19.02",
                "length": "1:22:11",
                "author": "Benjamin Grundy",
                "release": "2018-01-20T00:00:00.000Z",
                "description": "This week we unravel the cosmic serpent to find the origins of life and the link between DNA and Ayahuasca visions. Could the building blocks of all life also be a conscious force that is capable of direct communication with our altered states of mind?"
            }
        ]
    },
    {
        "_id": "5b893b2276c12c166c4e75b0",
        "season_number": 20,
        "name": "Season 20",
        "number_of_episodes": 9
    }, *and so on...*
]

Answer №1

If you want to filter data using the $filter operator in Aggregration, you can achieve this with the following query:

db.seasons.aggregate([
  { "$match": { "season_number": 19 } },
  { "$project": {
       "season_number": 1,
       "name": 1,
       "number_of_episodes": 1,
       "episodes": {
          "$filter": {
             "input":  "$episodes",
             "as": "episode",
             "cond": { "$eq": [ "$$episode.episode_number", 1 ] }
          }
       }
    } 
  }])

The $filter feature is supported from version 3.2 onwards.

Answer №2

db.users.aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$episodes",
            preserveNullAndEmptyArrays : false // keep arrays intact
        }
    },

    // Stage 2
    {
        $match: {
            "season_number" : 19.0,
            "episodes.episode_number" : 1
        }
    },

    // Stage 3
    {
        $group: {
            "_id":"$_id",
            "season_number" :{$last:"season_number"}, 
            "name" :{$last:"name"}, 
            "number_of_episodes" :{$last:"number_of_episodes"},
            "episodes":{$push:"$episodes"}
        }
    },
]);

Answer №3

update: utilized $filter method

originally discovered solution here

db.dumb.aggregate(
    {
        $match:{a:'ok', eps:{$elemMatch:{id:1}}}
    },
    {
        $project:{
            a:1, 
            eps:{
                $filter:{
                    input:'$eps', 
                    as:'ep', 
                    cond:{$eq:['$$ep.id',1]}
                }
            }
        }
    }
)

desired results

{ "_id" : ObjectId("5b8e3eb8e5ab5ef9a9b9b673"), "a" : "ok", "eps" : [ { "id" : 1, "comment" : "ok" } ] }
{ "_id" : ObjectId("5b8e3ec3e5ab5ef9a9b9b676"), "a" : "ok", "eps" : [ { "id" : 1, "comment" : "ok too" } ] }

consider using unwind?

constructing a dataset

> db.dumb.insert({a:'ok', eps:[{id:1, comment('ok')}]})
WriteResult({ "nInserted" : 1 })
> db.dumb.insert({a:'ko', eps:[{id:1, comment:'ok'}]})
WriteResult({ "nInserted" : 1 })
> db.dumb.insert({a:'ok', eps:[{id:2, comment:'ko'}]})
WriteResult({ "nInserted" : 1 })
> db.dumb.insert({a:'ok', eps:[{id:2, comment:'ko'}, {id:1, comment:'ok too'}]})
WriteResult({ "nInserted" : 1 })

matching the series (referred to as 'ok')

> db.dumb.find({a:'ok', eps:{$elemMatch:{id:1}}})
{ "_id" : ObjectId("5b8d447b21edbcdd7f3b3d24"), "a" : "ok", "eps" : [ { "id" : 1, "comment" : "ok" } ] }
{ "_id" : ObjectId("5b8d449d21edbcdd7f3b3d27"), "a" : "ok", "eps" : [ { "id" : 2, "comment" : "ko" }, { "id" : 1, "comment" : "ok too" } ] }

matching the movie with id 1 of the series named 'ok' by using unwind, each item in the array is expanded. Note the duplication of ObjectIds (for reference)

> db.dumb.aggregate({$match:{a:'ok'}},{$unwind:'$eps'})
{ "_id" : ObjectId("5b8d447b21edbcdd7f3b3d24"), "a" : "ok", "eps" : { "id" : 1, "comment" : "ok" } }
{ "_id" : ObjectId("5b8d449121edbc... // output truncated for brevity

standard match afterwards

> db.dumb.aggregate({$match:{a:'ok'}},{$unwind:'$eps'},{$match:{'eps.id':1}})
{ "_id" : ObjectId("5b8d447b21edbcdd7f3b3d24"), "a" : "ok", "eps" : { "id" : 1, "comment" : "ok" } }
{ "_id" : ObjectId("5b8d449d21edbcdd7f3b3d27"), "a" : "ok", "eps" : { "id" : 1, "comment" : "ok too" } }

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

Please replace the text with only letters and then submit it without any spaces, periods, commas, or other symbols

Whenever I encounter a form like this, I need to submit it and replace the text in the name field with only letters - no commas, spaces, or special characters. https://i.sstatic.net/9FQnT.png myform.html <script> function fixInput(event) { na ...

The Express session variable becomes inaccessible on different routes once it has been initialized on the login route

Despite encountering this question numerous times, I have yet to find a solution even after scouring through countless similar queries. The crux of the issue lies in having a node server with a mongodb database and a React frontend, where I aim to store us ...

Following the submission of a message, the textarea automatically inserts a line-break

Can someone please help me troubleshoot an issue with my chat app? Every time I try to send a message, the textarea adds a line break instead of just focusing on the textarea so I can send a new message smoothly. I have recorded a video demonstrating the ...

AngularJS: Eliminate an item from the location.search

Although there are many similar questions on SO, none of the answers have been able to help me so far. After poring over the Angular $window and $location documentation, I am still struggling to achieve my desired outcome in my client app. Consider a web ...

The most basic security measure for safeguarding a webpage

Currently, I am developing a website that requires customers to input a specific "code" in order to gain access. Upon visiting the site, users will be prompted to enter a simple code to proceed further. My programming skills are limited to HTML, CSS, and J ...

Add a new item to a collection using MongoTemplate

Here is the structure I am working with: { "_id" : "adddddddddddd", "_class" : "com.fluidm.service.identity.entity.Item", "itemName" : "satyam", "personList" : [ ] } Within a collection named "item," there is a list of persons stored ...

Dynamic updates using Ajax after a change in the trigger

In my current project, I am in the process of developing a textarea that will trigger an ajax request whenever it is changed. However, I am concerned about overloading the server with too many requests since the purpose of this request is to save the con ...

Misunderstanding the Variable Scope Concept in Node.js

I am struggling to comprehend why the return of an array from another function is confined to only one block of code. For example: exports.join = function(req, res){ User.findById(req.user._id, function(err, user) { var dupe = []; //placeholder arr ...

cheerio: Retrieve regular and text elements

When using cheerio to parse HTML code, I encountered an issue where using $("*") only returned normal HTML nodes and not separate text nodes. To illustrate my problem, consider the following user inputs: Input One: text only Desired Output: single text ...

Adding Zod validation for elements within an array in a React TypeScript application

Currently, I am utilizing Zod validation to confirm whether a given value is an email and also checking for the minimum length. However, I'm encountering an issue where if the field is left empty and the submit button is clicked, it displays the "requ ...

Utilizing Mysql Database Information in a JavaScript Widget

I am in the process of developing a widget that users can add to their blogs in order to drive traffic to my coupon code website. The goal is for the widget to retrieve information from the database and display the top 5 coupons of the day. This is what I ...

Implementing a BSON serialization/deserialization functionality in reactivemongo that supports arbitrary JSON branches, potentially utilizing the spray

I have been working on developing a REST API using the spray framework. Everything is functioning smoothly except for one particular case class: case class User(name: String, places: List[String], data: List[JsObject]) The main challenge lies in the data ...

What is the best way to showcase key-based values extracted from a text document?

I'm currently working on a file upload process that allows the user to display values based on a specific key, such as First Name. Below is a sample text: First Name : Joe Last Name : Smith Age : 21 My question is, how can I only display the values ...

Issue with Angular: PDF rendering delayed until window resize

Recently, I encountered an issue with rendering a PDF in Chrome while using an AJAX call with Angular. Strangely, the PDF would only show up in the browser if I resized the window or opened the console. Surprisingly, everything worked fine in Firefox. Jav ...

JavaScript came to a screeching halt

I was having issues with my JavaScript that validated a form, but now it's not working. I recently applied my template to the application and at some point, the functionality stopped. Any suggestions on what might have caused this? <!DOCTYPE HTML ...

Creating a unique 'full height' feature for the Material UI Dialog modal component

I'm encountering an issue with the fullScreen property on the Material UI Dialog component, which is being used as a modal. Following the documentation's recommendation, my code looks like this: import useMediaQuery from '@material-ui/core/u ...

Issues arise when attempting to integrate three.js with Angular 5, as compatibility

Recently embarking on a project that involves using three.js for graphics in Angular, I find myself challenged by my lack of experience in both Angular and three.js. The main issue I'm encountering is setting up three.js with Angular. Below is the set ...

Is there a way to retrieve the Angular-Redux store in a child module?

Within my Angular application, I utilize angular-redux for managing the application state. In my main module, I have defined the redux store in the following manner: export class MainModule { constructor(private ngRedux: NgRedux<MainAppState>, ...

Display and conceal multiple div elements using a timer

Currently, I am working on creating a message box that will display active messages one by one from a MySQL table. The challenge is that the number of divs needed can vary depending on the number of active messages in my database. Using an ajax timer and P ...

In JavaScript, what does this condition signify? if(display or true, then

The display option is not required in the function, but I am confused about its usage with || true Which part of the code actually evaluates this condition? if(display || true){...} if(display || true){ $("#container").fillContent(this.showReport(this.t ...