Reputation: 1189
How do you implement MongoDB's Schema Validation feature in Express server? I'm working on a simple todo app and decided to use the native MongoClient instead of mongoose but i still do want to have a schema.
Base on MongoDB's docs here: https://docs.mongodb.com/manual/core/schema-validation/#schema-validation You can either create a collection with Schema or update an existing collection without schema to have one. The commands are run in the mongo shell, but how do you implement it in express?
So far what i did is make a function that returns the Schema Validation commands and call it on every routes but i get an error saying db.runCommand is not a function.
Here's my express server:
const express = require("express");
const MongoClient = require("mongodb").MongoClient;
const ObjectID = require("mongodb").ObjectID;
const dotenv = require('dotenv').config();
const todoRoutes = express.Router();
const cors = require("cors");
const path = require("path");
const port = process.env.PORT || 4000;
const dbName = process.env.DB_NAME;
let db;
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
MongoClient.connect(process.env.MONGO_URI,{useNewUrlParser: true},(err,client)=>{
if(err){
throw err;
console.log(`Unable to connect to the databse: ${err}`);
} else {
db = client.db(dbName);
console.log('Connected to the database');
}
});
/* Schema Validation Function */
const runDbSchemaValidation = function(){
return db.runCommand( {
collMod: "todos",
validator: { $jsonSchema: {
bsonType: "object",
required: [ "description", "responsible","priority", "completed" ],
properties: {
description: {
bsonType: "string",
description: "must be a string and is required"
},
responsibility: {
bsonType: "string",
description: "must be a string and is required"
},
priority: {
bsonType: "string",
description: "must be a string and is required"
},
completed: {
bsonType: "bool",
description: "must be a either true or false and is required"
}
}
} },
validationLevel: "strict"
} );
}
/* Get list of Todos */
todoRoutes.route('/').get((req,res)=>{
runDbSchemaValidation();
db.collection("todos").find({}).toArray((err,docs)=>{
if(err)
console.log(err);
else {
console.log(docs);
res.json(docs);
}
});
});
/* Get Single Todo */
todoRoutes.route('/:id').get((req,res)=>{
let todoID = req.params.id;
runDbSchemaValidation();
db.collection("todos").findOne({_id: ObjectID(todoID)}, (err,docs)=>{
if(err)
console.log(err);
else {
console.log(docs);
res.json(docs);
}
});
});
/* Create Todo */
todoRoutes.route('/create').post((req,res,next)=>{
const userInput = req.body;
runDbSchemaValidation();
db.collection("todos").insertOne({description:userInput.description,responsible:userInput.responsible,priority:userInput.priority,completed:false},(err,docs)=>{
if(err)
console.log(err);
else{
res.json(docs);
}
});
});
/* Edit todo */
todoRoutes.route('/edit/:id').get((req,res,next)=>{
let todoID = req.params.id;
runDbSchemaValidation();
db.collection("todos").findOne({_id: ObjectID(todoID)},(err,docs)=>{
if(err)
console.log(err);
else {
console.log(docs);
res.json(docs);
}
});
});
todoRoutes.route('/edit/:id').put((req,res,next)=>{
const todoID = req.params.id;
const userInput = req.body;
runDbSchemaValidation();
db.collection("todos").updateOne({_id: ObjectID(todoID)},{ $set:{ description: userInput.description, responsible: userInput.responsible, priority: userInput.priority, completed: userInput.completed }},{returnNewDocument:true},(err,docs)=>{
if(err)
console.log(err);
else
res.json(docs);
console.log(db.getPrimaryKey(todoID));
});
});
/* Delete todo */
todoRoutes.route('/:id').delete((req,res,next)=>{
const todoID = req.params.id;
runDbSchemaValidation();
db.collection("todos").deleteOne({_id: ObjectID(todoID)},(err,docs)=>{
if(err)
console.log(err)
else{
res.json(docs);
}
});
});
app.use('/todos',todoRoutes);
app.listen(port,()=>{
console.log(`Server listening to port ${port}`);
});
I also tried it on the initial client connection but i got the same error:
Upvotes: 2
Views: 2139
Reputation: 26
You validation schema will be added to the MongoDB driver when you run it for the first time. So you don't need to perform validation every time you run a query. You will get a validation response directly from the driver's validation schema that was added initially. Again you will not explicitly get to know which object is causing the error. The validation response will be more generic.
Upvotes: 1