Express api with mongoose PUT - node.js

I have endpoint:
router.put('/:customerId', async (req, res) => {
try {
const updatedCustomer = await Customer.updateOne(
{ _id: req.params.customerId },
req.body,
{ new: true }
);
res.send(updatedCustomer);
} catch {
res.json({ message: err });
}
});
const CustomerSchema = mongoose.Schema({
name: String,
surname: String
})
and after put request with only name value in my object still exist name and surname. I thought that my surname value will be delete. It works fine or not?

In your schema definition do the following
const CustomerSchema = mongoose.Schema({
name: String,
surname: String
},{
strict:false
})

Related

insert to MongoDB array with axios, restAPI and nodeJS

I am trying to add an item to a MongoDB array with RESTAPI through Axios. I thought it would look similar to the push method but I have no idea how to do that.
my Model is of a person:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [],
missions: []
})
const personModel = mongoose.model('Person', PersonSchema);
I want to add a mission to the mission array of a person.
and for example, in order to add a new Person, I use NodeJS and API:
(api.js)
router.post('/api/people', (req, res) => {
const personToAdd = req.body;
const newPersonPost = new personModel(personToAdd);
newPersonPost.save((e) => {
if (e) {
console.log("error");
}
});
res.json({
msg: 'Received'
})
});
and in the client side I use Axios:
axios({
url: 'http://localhost:8080/api/people',
method: 'POST',
data: dataToUpdate
})
.then(() => {
console.log('axios sent info to server');
}).catch((e) => {
console.log('error' + e);
})
Thank you so much!
express
router.post('updating mission endpoint url', async (req, res) =>
try {
const query = { /* content */}; /* write a query to retrieve the concerned user by using a unique identifier */
let person = await personModel.findOne(query);
person.missions.push(req.body.mission);
personModel.save();
} catch (err) {
console.log(err);
}
});
client
In the client side you just have to put the mission you want to add in data like you did above with the right endpoint url and you should add a unique identifier for the user you want to add mission to.
[] will not assign array type to your variable.
Change your schema file with the following:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: { type: String },
password: { type: String },
friends: { type: Array },
missions: { type: Array }
})
Update the db model entity file with following
First method:
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: {type : Array},
missions: {type : Array}
})
const personModel = mongoose.model('Person', PersonSchema);
Second Method :
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
password: String,
friends: [{ type: String }],
missions: [{ type: String }]
})
const personModel = mongoose.model('Person', PersonSchema);
You can update the array object as per your requirements.
You just want to be using the $push update operator, very simple, like so:
db.collection.updateOne(
{
_id: user._id
},
{
"$push": {
"missions": {
mission: newMission
}
}
})
Mongo Playground

mongoose.Schema.Types.ObjectId is giving an empty array when console.logged

This is my table schema
var mongoose=require("mongoose");
var tableSchema=new mongoose.Schema({
tName:String,
keys:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"key"
}
],
fields:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"field"
}
]
})
module.exports=mongoose.model("table",tableSchema);
----Key Schema
var mongoose=require("mongoose")
var keySchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("key",keySchema);
---field Schema
var mongoose=require("mongoose")
var fieldSchema=new mongoose.Schema({
name:[String],
value:[String]
})
module.exports=mongoose.model("field",fieldSchema);
----How I Pushed into
app.post("/table/:id/value",function(req,res){
var Key={
name:req.body.key,
value:req.body.keyValue
}
var Field={
name:req.body.field,
value:req.body.fieldValue
}
table.findById(req.params.id,function(err,foundTable){
if(err){
console.log(err)
}
else{
console.log(foundTable)
key.create(Key,function(err,createKey){
foundTable.keys.push(createKey)
console.log(createKey)
})
field.create(Field,function(err,createField){
foundTable.fields.push(createField)
console.log(createField)
})
foundTable.save();
console.log(foundTable);
res.redirect("/table/"+req.params.id)
}
})
})
ObjectId are not being refernced
Here is the Image that prints the table
How I populated the table
app.get("/table/:id",function(req,res){
table.findById(req.params.id).populate("keys").populate("fields").exec(function(err,foundTable){
if(err){
console.log(err)
res.redirect("/")
}
else{
console.log(foundTable);
res.render("show",{table:foundTable})
}
})
})
I Dont know where I had gone wrong,
everything seems to be fine but
the objected is not referenced when printed and
it is not being populated
How it should be printed reference: https://bezkoder.com/mongoose-one-to-one-relationship-example/
This is an example:
1st schema
const mongoose = require("mongoose");
const Customer = mongoose.model(
"Customer",
new mongoose.Schema({
name: String,
age: Number,
gender: String
})
);
module.exports = Customer;
2nd schema
const mongoose = require("mongoose");
const Identifier = mongoose.model(
"Identifier",
new mongoose.Schema({
cardCode: String,
customer: {
type: mongoose.Schema.Types.ObjectId,
ref: "Customer"
}
})
);
module.exports = Identifier;
How it should be printed
{
_id : ObjectId("5da000be062dc522eccaedeb"),
cardCode : "5DA000BC06",
customer : ObjectId("5da000bc062dc522eccaedea"),
__v : 0
}
How it should be populated
[ { _id: 5da135bf61a1dd3e9c2a6e82,
cardCode: '5DA135BD61',
customer:
{ _id: 5da135bd61a1dd3e9c2a6e81,
name: 'bezkoder',
age: 29,
gender: 'male',
__v: 0 },
__v: 0 } ]
try this .populate([ 'keys', 'fields' ])
The reason why keys and fields are not inserted is that the foundTable.save() will be executed before creating the new Key and Field documents and push there _id to the foundTable.
One way to solve the issue is by using async/await. You can modify your code as below using async/await
app.post("/table/:id/value", async function (req, res) {
var Key = {
name: req.body.key,
value: req.body.keyValue,
};
var Field = {
name: req.body.field,
value: req.body.fieldValue,
};
try {
const foundTable = table.findById(req.params.id);
const createKey = await key.create(Key);
const createField = await field.create(Field);
foundTable.keys.push(createKey._id);
foundTable.fields.push(createField._id);
await await foundTable.save();
res.redirect("/table/"+req.params.id)
} catch (err) {
console.log(err);
// handle failure here
}
});
This will make sure the Key and Field are created and _id is pushed to foundTable before saving the foundTable
Regarding the populate query. Looks like once you save the _id of Field and Key in foundTable your existing query itself should work

Node express find and return response multple models

I'm fairly new to node & express, I'm trying to implement a register application.
I have 2 models, both models have one common field 'empID'.
const RegisterEntriesSchema = mongoose.Schema({
empID: Number,
registerType: String,
registerItemsQuantity: Number,
registerItemsDesc: String
}, {
timestamps: true
});
const RegisterEmpSchema = mongoose.Schema({
empID: Number,
empName: String,
empPhone: String,
empProj:String
}, {
timestamps: true
});
For my get call in which I need to merge the values, I get from RegisterEmpSchema with its corresponding
employee details from RegisterEmpSchema.
exports.findAllRegisterEntries = (req, res) => {
registerEntriesModel.find()
.then(result => {
var updatedResponse=[];
console.log(result[0].empID);
for(var i=0;i<result.length;i++){
registerEmpModel.find({ empID: result[i].empID })
.then(result2 => {
**//unable to access result here**
}).catch(err => {
console.log("exception catch called findAllRegisterEntries, find employee details "+err);
});
}
res.send(updatedResponse);
}).catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving register."
});
});
};
I basically need to get register data and its corresponding employee data.
How do I modify my find() code to use the key empID and do a join query fetch?
I think you better use populate, add ref to empID inside RegisterEntriesSchema
const RegisterEmpSchema = new mongoose.Schema({
empID: Number,
empName: String,
empPhone: String,
empProj: String
}, {
timestamps: true
});
const registerEmpModel = mongoose.model('RegisterEmpSchema', RegisterEmpSchema, 'registerEmployeeCollection');
const RegisterEntriesSchema = new mongoose.Schema({
registerType: String,
registerItemsQuantity: Number,
registerItemsDesc: String,
empID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'RegisterEmpSchema'
}
}, {
timestamps: true
});
RegisterEntriesSchema.index({ createdAt: 1 }, { expires: '525601m' });
const registerEntriesModel = mongoose.model('RegisterEntriesSchema', RegisterEntriesSchema, 'registerEntriesCollection');
module.exports = {
registerEmpModel, registerEntriesModel,
}
then use populate() to populate the RegisterEntriesSchema with correspondence empID
RegisterEntriesSchema.
find().
populate('empID').
exec(function (err, data) {
if (err) return console.log(err);
res.send(data);
});
check mongoose docs: https://mongoosejs.com/docs/populate.html

How to find client from bills by id

I need to find client from bills by id client, but it shows me an error.
I've tried to get client id using function "findById"
this is the Client schema:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const clientSchema = new Schema({
name: String,
mail: String,
cuil: String,
phone: Number,
address: {street: String,
number: Number,
floor: String,
flat: Number
}
});
mongoose.model('clients', clientSchema);
Bill schema:
const mongoose = require('mongoose');
const { Schema } = mongoose;
const billSchema = new Schema({
number: Number,
date: {type: Date, default: Date.now()},
type: String,
local: String,
client: {
type: mongoose.Schema.Types.ObjectId,
ref: 'clients'
},
detail: [{
quantity Number,
product: {code: Number,
number: String,
price: Number
},
undertotal: Number
}
],
total: Number
});
mongoose.model('bills', billSchema);
And by last, my get route
app.get('/api/bills/client/:id', (req, res) => {
console.info('Obtaining bill's client');
try{
const id = req.body.client._id;
const client = Bill.findById(id)
.populate("client","address name mail cuil phone -_id");
if (client) {
res.send(client);
} else {
res.status(404).send({ message: `Client '${id}' couldn't be found. `
});
}
} catch (err) {
console.log(err);
res.status(500).send({ message: `Internal server error.\n\n${err}` });
}
});
I expected shows me the client from bill.
The output shows me "Internal server error". How can I solve this error?.
Is better using function "find" instead "findById"?
Are you trying to pass the clientId through req.body or inside the route parameter?
I think it must be in route parameter since you have already expect it in url like this "/api/bills/client/:id"
Note: findOne (or findById) returns promise so you need to use await (or then block))
app.get("/api/bills/client/:id", async (req, res) => {
console.info("Obtaining bills client");
try {
const id = req.params.id; // req.body.client._id;
const client = await Bill.findOne({ client: id }).populate(
"client",
"address name mail cuil phone -_id"
);
if (client) {
res.send(client);
} else {
res.status(404).send({ message: `Client '${id}' couldn't be found. ` });
}
} catch (err) {
console.log(err);
res.status(500).send({ message: `Internal server error.\n\n${err}` });
}
});
You are finding bill id, then how will you get data, Try for the following:
const id = req.body.client._id;
const client = Bill.findOne({client:id})
.populate("client","address name mail cuil phone -_id");

How to do proper validation for array of objects ids in nodeJS rest api

I am currently struggling to implement rest api build in nodeJS, mongoDB, express. One of fields takes array of objects ids (field sprints in model project). The question is how to do proper validation in route file (projects.js) when doing post method (keeping in mind that field sprints is not required)?
I was trying to check typeof req.body.sprints and also to do lenght on this, but with no result. I was also trying to find answer on stackoverflow etc., but didn't came across nothing similar.
project.js (model file)
const mongoose = require("mongoose");
const Project = mongoose.model(
"Project",
new mongoose.Schema({
name: {
...
sprints: [
{
type: new mongoose.Schema({
name: {
type: String,
required: true,
minlength: 5,
maxlength: 255
},
isClosed: { type: Boolean, default: false }
})
}
]
})
);
function validateProject(project) {
const schema = {
name: Joi.string()
.min(5)
.max(255)
.required(),
createdBy: Joi.objectId().required(),
isClosed: Joi.boolean(),
sprints: Joi.array().items(Joi.objectId())
};
return Joi.validate(project, schema);
}
exports.Project = Project;
exports.validate = validateProject;
projects.js (route file)
const express = require("express");
const { User } = require("../models/user");
const { Sprint } = require("../models/sprint");
const { Project, validate } = require("../models/project");
const router = express.Router();
...
/* POST project */
router.post("/", async (req, res) => {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
const user = await User.findById(req.body.createdBy);
if (!user) return res.status(400).send("Invalid user");
const sprint = await Sprint.findById(req.body.sprints);
if (!sprint) return res.status(400).send("Invalid sprint");
//i think that here i have to validate if sprint has even one
element and only then do object id validation
const project = new Project({
name: req.body.name,
createDate: req.body.createDate,
createdBy: { _id: user._id, name: user.name },
isClosed: req.body.isClosed,
sprints: [
{
_id: sprint._id,
name: sprint.name,
isClosed: sprint.isClosed
}
]
});
await project.save();
res.send(project);
});
...
module.exports = router;
In my post method i am checking if given id exist in table Sprints but i have problem if no sprint id is provided (i get 'Invalid sprint' message). Expected result will be: i can provide array of sprints, one sprint, or none at all.
try this out
function validateProject(project) {
const schema = {
name: Joi.string()
.min(5)
.max(255)
.required(),
createdBy: Joi.objectId().required(),
isClosed: Joi.boolean(),
sprints:Joi.array().items(
Joi.object({
name: Joi.string(),
isClosed: Joi.boolean
})
)
})
};
return Joi.validate(project, schema);
}

Resources