ifa-odm
Ifa-odm is a MongoDB Object Document Mapper (ODM) for basic mongo db crud operations and $Jsonschema Validation. ifa-odm supports Node.js and Express.js
Documentation
Installation
First install Node.js and MongoDB. Then:
npm install ifa-odm
Importing
const { Ifa, connect } = require("ifa-odm");
import { Ifa, connect } from "ifa-odm";
let dbUri = "mongodb://localhost:27017/";
let dbName = "testing";
const ifa = new Ifa(dbUri, dbName);
ifa.connect().then(() => console.log("database connected successfully"));
Note: If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed.
Defining a Model
Models are defined through the Schema
interface.
const { Schema } = require("ifa-odm");
import { Schema } from "ifa-odm";
const user = new Schema(
"user",
{
firstName: { type: "string", required: true },
lastName: { type: "string", required: true },
age: { type: "number", required: true },
email: { type: "string", unique: true },
isGraduated: { type: "bool", required: true },
records: [
{
score: { type: "number" },
cgpa: { type: "number" },
},
],
address: {
street: { type: "string" },
city: { type: "string" },
state: { type: "string" },
zipCode: { type: "string" },
zip: [{ type: "string" }],
},
hobbies: [{ type: "string" }],
},
{ timestamps: true }
);
Crud operations with ifa-odm
app.post("/users", async (req, res) => {
const userData = {
firstName: "John",
lastName: "Doe",
age: 32,
isGraduated: false,
email: "johndoe@gmail.com",
records: [{ cgpa: 4, score: 70 }],
address: {
street: "Lagos",
city: "Lagos",
state: "Lagos",
zip: ["100001"],
},
hobbies: ["reading", "cooking"],
};
try {
const result = await user.create(userData);
res.json(result);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.get("/users", async (req, res) => {
try {
const result = await user.find().exec();
res.json(result);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.get("/users/:id", async (req, res) => {
const { id } = req.params;
try {
const result = await user.findOne({ _id: id }).exec();
res.json(result);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.put("/users/:id", async (req, res) => {
const { id } = req.params;
const { firstName, lastName, age, isGraduated, email } = req.body;
const userData = {
firstName,
lastName,
age,
isGraduated,
email,
};
try {
const result = await user.updateOneById(id, userData);
res.json(result);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
app.delete("/users/:id", async (req, res) => {
const { id } = req.params;
try {
const result = await user.removeOneById(id);
res.json(result);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
Data Association By Reference
ifa-odm supports data association by reference.
It support both object reference and array reference as shown in the code snippet below.
const blog = new Schema(
"blog",
{
title: { type: "string" },
desc: { type: "string" },
user: { type: "ref", ref: "users", refField: "_id", required: true },
},
{ timestamps: true }
);
NB the "ref" key is the collection name which is being referenced, while "refField" is the field on the collection's object that is referenced, which in most use cases the "_id" field.
Add data to a referenced field
app.post("/blogs", async (req, res) => {
const { title, desc } = req.body;
try {
const users = await user.find().exec();
const newBlog = await blog.createMany([
{
title: "new blog",
desc: "new blog description",
user: users[0]._id,
},
{
title: "new blog 2",
desc: "new blog description 2",
user: users[0]._id,
},
]);
res.status(201).json(newBlog);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
Populating Associated Data
ifa-odm has supported for associated data population
app.get("/blogs", async (req, res) => {
try {
const blogs = await blog.find().populate("user").exe();
res.status(200).json(blogs);
} catch (error) {
if (error instanceof Error) {
res.status(400).json({ error: error.message });
}
}
});
app.get("/blogs", async (req, res) => {
try {
const blogs = await blog
.find()
.populate("user", { firstName: 1, lastName: 1, email: 0 })
.exe();
res.status(200).json(blogs);
} catch (error) {
if (error instanceof Error) {
res.status(400).json({ error: error.message });
}
}
});
Query Response Projection
ifa-odm supports query projection for find findOne and findOneById
methods. The projection object to a query defines which field of the query document to be added or removed
await user.find({}, { firstName: 0 }).exec();
await user.findOneById("6822142cf7643e7fab634770", { firstName: 0 }).exec();
Sort and Limit Operations
ifa-odm supports the sort and limit operations. With the limit operation, database read queries can be paginatted while dealing with large data-set.
await user.find({}, { firstName: 0 }).limit(5).sort({ createdAt: -1 }).exec();
Note for the sort operation, "-1" sorts documents in a descending order, while "1" sorts documents in an ascending order