Search code examples
javascriptnode.jsmongodbmerndao

My Query Quagmire: My node.js program works just fine, except when I try to execute queries, or filtered HTTP requests. Why?


I have been working on the backend of my app. At this point, it can access all data in a data base, and output it. I'm trying to implement some queries, so that the user can filter out the content that is returned. My DAL/DAO, looks like this

let mflix   //Creates a variable used to store a ref to our DB

class MflixDAO {
    static async injectDB(conn){    
        if(mflix){
            return
        }
        
        try{
            mflix = await conn.db(process.env.JD_NS).collection("movies")
        }catch(e){
            console.error('Unable to establish a collection handle in mflixDAO: ' + e)
        }
    }

    // Creates a query to fetch data from the collection/table in the DB
    static async getMovies({
        
        mflix.controller
        filters = null,
        page = 0,
        moviesPerPage = 20,
    } = {}) {
        let query
        
        if (filters){
            // Code
            if("year" in filters){
                query = {"year": {$eq: filters["year"]}}
            }
            // Code
        }

        // Cursor represents the returned data
        let cursor
        
        try{
            cursor = await mflix.find(query)
        }catch(e){
            console.error('Unable to issue find command ' + e)
            return {moviesList: [], totalNumMovies: 0}
        }

        const displayCursor = cursor.limit(moviesPerPage).skip(moviesPerPage * page)

        try{
            const moviesList = await displayCursor.toArray()    // Puts data in an array
            const totalNumMovies = await mflix.countDocuments(query)  // Gets total number of documents

            return { moviesList, totalNumMovies}
        } catch(e){
            console.error('Unable to convert cursor to array or problem counting documents ' + e)
            return{moviesList: [], totalNumMovies: 0}
        }
        
    }
}

export default MflixDAO

Just so you know, I am using a sample database from MongoDB Atlas. I am using Postman to test HTTP requests. All the data follows JSON format

Anyway, when I execute a basic GET request. The program runs without any problems. All the data outputs as expected. However, if I execute something along the lines of

GET http://localhost:5000/api/v1/mflix?year=1903

Then moviesList returns an empty array [], but no error message.

After debugging, I suspect the problem lies either at cursor = await mflix.find(query) or displayCursor = cursor.limit(moviesPerPage).skip(moviesPerPage * page), but the callstacks for those methods is so complex for me, I don't know what to even look for.

Any suggestions?

Edit: Here is an example of the document I am trying to access:

{
     "_id": "573a1390f29313caabcd42e8",
     "plot": "A group of bandits stage a brazen train hold-up, only to find a determined posse hot on their heels.",
      "genres": [
          "Short",
          "Western"
      ],
      "runtime": 11,
      "cast": [
          "A.C. Abadie",
          "Gilbert M. 'Broncho Billy' Anderson",
          "George Barnes",
          "Justus D. Barnes"
      ],
      "poster": "https://m.media-amazon.com/images/M/MV5BMTU3NjE5NzYtYTYyNS00MDVmLWIwYjgtMmYwYWIxZDYyNzU2XkEyXkFqcGdeQXVyNzQzNzQxNzI@._V1_SY1000_SX677_AL_.jpg",
      "title": "The Great Train Robbery",
      "fullplot": "Among the earliest existing films in American cinema - notable as the first film that presented a narrative story to tell - it depicts a group of cowboy outlaws who hold up a train and rob the passengers. They are then pursued by a Sheriff's posse. Several scenes have color included - all hand tinted.",
      "languages": [
          "English"
      ],
      "released": "1903-12-01T00:00:00.000Z",
      "directors": [
          "Edwin S. Porter"
      ],
      "rated": "TV-G",
      "awards": {
          "wins": 1,
          "nominations": 0,
          "text": "1 win."
      },
      "lastupdated": "2015-08-13 00:27:59.177000000",
      "year": 1903,
      "imdb": {
          "rating": 7.4,
          "votes": 9847,
          "id": 439
      },
      "countries": [
          "USA"
      ],
      "type": "movie",
      "tomatoes": {
          "viewer": {
              "rating": 3.7,
              "numReviews": 2559,
              "meter": 75
          },
          "fresh": 6,
          "critic": {
              "rating": 7.6,
              "numReviews": 6,
              "meter": 100
          },
          "rotten": 0,
          "lastUpdated": "2015-08-08T19:16:10.000Z"
      },
      "num_mflix_comments": 0
  }

EDIT: It seems to be a datatype problem. When I request a data with a string/varchar type, the program returns values that contain that value. Example:

Input:
GET localhost:5000/api/v1/mflix?rated=TV-G

Output:
{
    "_id": "XXXXXXXXXX"
    // Data
    "rated" = "TV-G"
    // Data
}

EDIT: The problem has nothing to do with anything I've posted up to this point it seems. The problem is in this piece of code:

let filters = {}
        if(req.query.year){
            filters.year = req.query.year // This line needs to be changed
        }

        const {moviesList, totalNumMovies} = await MflixDAO.getMovies({
            filters,
            page,
            moviesPerPage,
        })

I will explain in the answer below


Solution

  • Ok so the problem, as it turns out, is that when I make an HTTP request, the requested value is passed as a string. So in

    GET http://localhost:5000/api/v1/mflix?year=1903
    

    the value of year is registered by the program as a string. In other words, the DAO ends up looking for "1903" instead of 1903. Naturally, year = "1903" does not exist. To fix this, the line filters.year = req.query.year must be changed to filters.year = parseInt(req.query.year).