1

I want to preface by saying I have looked for this issue online and found solutions using mongoose, I do not use that so I don't know how well it translate here. Plus, I also using async/await instead of .then, so my code is different.

My question is that the API I have made in ExpressJS is super slow compared to the same API I have in Flask. I tried seeing why this is an issue, since JS is supposed to be faster than Python. I noticed it was due to me connecting to Mongo each time. I need to do this as my MongoDB has a different databases for different clients, so I cannot just have 1 constant connection to one database. Below is my Mongo code.

const {MongoClient} = require('mongodb');
const client = new MongoClient("mongodb+srv://abc@xyz.mongodb.net/<Cluster");

class MongoMethods {
    constructor(company, collection){
        this.company = company;
        this.collection = collection;
    }

    async get(accessParameters){
        try{
            await client.connect();
            const db = client.db(this.company);
            const collection = db.collection(this.collection);
            const val = await collection.findOne({"_id":accessParameters["at"]});
            return val
        } finally {
            await client.close();
        }
    }

   async putIn(putParameters, type){
        try{
            await client.connect();
            const db = client.db(this.company);
            const collection = db.collection(this.collection);
            
            var existing = await collection.findOne({"_id":putParameters["at"]});

            if(type === "array"){
                var toAdd = existing !== undefined && putParameters["in"] in existing? existing[putParameters["in"]] : [];
                toAdd.push(putParameters["value"]);
            }else if(type === "dict"){
                var toAdd = existing !== undefined && putParameters["in"] in existing? existing[putParameters["in"]] : {};
                toAdd[putParameters["key"]] = putParameters["value"];
            }else{
                var toAdd = putParameters["value"];
            }
            
            await collection.updateOne({"_id":putParameters["at"]}, {"$set": {[putParameters["in"]]: toAdd}}, {upsert: true});
        } finally {
            await client.close();
        }
    }

    async remove(removeParameters){
        try{
            await client.connect();
            const db = client.db(this.company);
            const collection = db.collection(this.collection);

            if(removeParameters["key"] !== undefined){
                await collection.updateOne({"_id":removeParameters["at"]}, {"$unset": {[removeParameters["in"] + "." + removeParameters["key"]] : ""}})
            }else if(removeParameters["in"] !== undefined){
                await collection.updateOne({"_id":removeParameters["at"]}, {"$unset": {[removeParameters["in"]] : ""}})
            }else{
                await collection.deleteOne({"_id":removeParameters["at"]})
            }

            
        }finally{
            await client.close();
        }
    }
}

module.exports.MongoMethods = MongoMethods;

Below is how functions in my ExpressJS file look (I cannot post this file so this is an excerpt):

var express = require('express');
var cors = require('cors')
const bodyParser = require('body-parser');
const { validate, ValidationError } = require('express-superstruct');
const { MongoMethods } = require('./mongo.js')

let app = express()
app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.route('/enp1/')
  .get(validate({uid : "string", site : "string"}), function (req, res) {
    var args = req.query
    var mongoClient = new MongoMethods(args.site, "collection_1")
    mongoClient.get({at : args.uid}).catch(console.dir).then(result => {
      if(result == undefined){ // This may need to take into account an empty dict
        res.status(404).json({"Database Error" : "UID does not exists or site is not a valid website"})
      }
      res.status(200).json(result)
    })
  })

app.route('/enp2/')
  .put(validate({site : "string", uid : "string", time : "string"}), function (req, res) {
    var args = req.body;

    var mongoClient = new MongoMethods(args.site, "time")

    mongoClient.putIn({at : args.uid, in : "time", value : parseInt(args.time)}, "int").catch(console.dir).then(result => {
      res.status(200).end()
    })
  })

It seems like this code is connecting to Mongo each time as I have to initialize the MongoMethods object each time. Can I prevent it from trying to connect each time so that my API doesn't have slow speeds? When I compare speeds, JS endpoints without Mongo are 50% faster than their Python counterpart but when using Mongo endpoints, it is around 300ms slower.

Let me know if you need anymore clarification.

Thanks in advance!

Edit 1: I wanted to mention, the API runs on AWS API Gateway and AWS Lambda@Edge functions.

Pshivvy
  • 573
  • 3
  • 12
  • look over it [stackoverflow solution to connect mongo globally](https://stackoverflow.com/questions/49397608/what-is-best-way-to-handle-global-connection-of-mongodb-in-nodejs) . It may help you. – jifakir Aug 09 '21 at 04:16
  • @jifakir From what I see on the link, my get, put, etc functions will all need to be put in one file. I want to keep them isolated so that I do not have duplicated. How will I go about working with this? – Pshivvy Aug 09 '21 at 05:50
  • Also, it seems like this code would not be useful for multiple databases, as that is my use case, unless the way would be to change the Connection.db value each time? – Pshivvy Aug 09 '21 at 06:04

0 Answers0