MongoDB Atlas provides a set of API endpoints that can be used to access the database hosted on Atlas without the need for database drivers; great for minimal memory footprint, especially on serverless infrastructures such as AWS Lambda.
Instead of bare-bone API calls directly, we can create a helper client and wrap the logic we want in methods. We won’t use axios or any third-party package but use the native https
module.
The Code
import * as https from "https";
const defaultOptions = {
protocol: 'https:',
hostname: process.env.MONGO_HOST_NAME,
port: 443,
method: 'POST',
path: process.env.MONGO_PATH,
headers: {
'Content-Type': 'application/json',
"Access-Control-Request-Headers": "*",
'api-key': process.env.MONGO_DATA_API_KEY,
}
};
const postBody = {
"database": process.env.MONGO_DATABASE,
"dataSource": process.env.MONGO_DATASOURCE
};
const post = ({ collection, action, data, update, filter, projection }) => {
const options = {
...defaultOptions,
path: defaultOptions.path + action
};
return new Promise((resolve, reject) => {
const req = https
.request(options, (res) => {
res.setEncoding("utf8");
let body = "";
res.on("data", (chunk) => (body += chunk));
res.on("end", () => {
resolve(JSON.parse(body))
});
})
.on("error", reject);
req.write(JSON.stringify({
...postBody,
collection,
filter: filter ?? undefined,
document: data ?? undefined,
projection: projection ?? undefined,
update: update ?? undefined
}));
req.end();
});
};
const findOne = async ({ collection, filter, projection }) => {
try {
const result = await post({ collection, action: "findOne", filter, projection });
if (!result || result.document === undefined) {
console.log(result);
throw new Error();
}
return result.document;
} catch (e) {
console.log(e);
throw new Error();
}
}
const findMany = async ({ collection, filter, projection }) => {
try {
const result = await post({ collection, action: "find", filter, projection });
if (!result.documents) {
console.log(result);
throw new Error();
}
return result.documents;
} catch (e) {
console.log(e);
throw new Error();
}
}
const insertOne = async ({ collection, data }) => {
try {
const result = await post({ collection, action: "insertOne", data });
if (!result.insertedId) {
console.log(result);
throw new Error();
}
return result.insertedId;
} catch (e) {
console.log(e);
throw new Error();
}
}
const updateOne = async ({ collection, filter, data, pushData }) => {
try {
const update = {
"$set": data,
"$push": pushData ?? undefined
}
const result = await post({ collection, action: "updateOne", filter, update });
if (result.matchedCount === undefined) {
console.log(result);
throw new Error();
}
return result;
} catch (e) {
console.log(e);
throw new Error();
}
}
export { findOne, findMany, insertOne, updateOne };
In all these methods, you must pass collection
as required and other relevant data to perform different operations on your database.
For these APIs to work, you must set up an API key from Atlas dashboard and provide it in the env variable process.env.MONGO_DATA_API_KEY
.
You can add type safety to this code with TypeScript.
See also
- SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
- Exactly Same Query Behaving Differently in Mongo Client and Mongoose
- MongoDB Single Update Query to Change the Field Name in All Matching Documents of the Collection
- AWS Layer: Generate nodejs Zip Layer File Based on the Lambda's Dependencies
- In Node JS HTML to PDF conversion, Populate Images From URLs
- Convert HTML to PDF in Nodejs
- JavaScript Rollbar: Unknown Unhandled Rejection Error Getting Reason From Event