How to find client from bills by id - node.js

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");

Related

Express api with mongoose PUT

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
})

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

Find an existing id object in post web service bill

I want to find an existing id object when I post a bill, but I don't know how find it to save the bill. I want it works from back end and front end.
This is my bill model:
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"
},
provider: {
type: mongoose.Schema.Types.ObjectId,
ref: "providers"
},
detail: [
{
quantity: Number,
product: {
code: Number,
name: String,
price: Number
},
undertotal: Number
}
],
total: Number
});
module.exports = mongoose.model("bills", billSchema);
And this is my post service:
app.post("/api/bills", async (req, res) => {
const { number, type, local, detail, total } = req.body;
let existingClient = await Client.findById(Client._id);
if (!existingClient) {
return res.status(404).json({
message: "not found client"
});
}
let existingProvider = await Provider.findById(Provider._id);
if (!existingProvider) {
return res.status(404).json({
message: "not found provider"
});
}
if (
!existingClient._id ||
(existingClient._id &&
mongoose.Types.ObjectId() ===
(await Client.findById(existingClient._id).select("_id")))
) {
const clientId = mongoose.Types.ObjectId();
this.existingClient._id = clientId;
}
if (
!existingProvider._id ||
(existingProvider._id &&
mongoose.Types.ObjectId() ===
(await Provider.findById(existingProvider._id).select("_id")))
) {
const providerId = mongoose.Types.ObjectId();
this.existingProvider._id = providerId;
}
const bill = new Bill({
number,
date: new Date(),
type,
local,
client: clientId,
provider: providerId,
detail,
total
});
try {
let newBill = await bill.save();
res.status(201).send(newBill);
} catch (err) {
if (err.name === "MongoError") {
res.status(409).send(err.message);
}
console.log(err);
res.status(500).send(err);
}
});
The expected output is bill saved with client and provider ids but real output is an error message saying "cannot read property _id of undefined"
What is wrong?

I get this error "Cast to String failed for value \"{}\" at path \"body\"" When saving post data to my mongodb collection, Nodejs

I can't save anything to my new mongodb collection because I keep getting this error
"message": "Cast to String failed for value \"{}\" at path \"body\""
I've successfully used models to add data to my mongodb collections with no issue in the past, but I tried to create a new model today and when I decided to test it using postman I kept getting this error . I tried reading online but couldn't find an answer, please help.
Here's my schema for this
const mongoose = require("mongoose");
const ticketSchema = new mongoose.Schema({
sender: {
type: String
},
body: {
type: String,
required: true
},
ticketStyle: {
type: String
},
ticketStatus: {
type: String
},
response: {
type: String,
required: false
}
});
const Ticket = mongoose.model("Ticket", ticketSchema);
module.exports = Ticket;
and here is the route
router.post("/support", (req, res) => {
const body = req.body;
const sender = "admin";
const ticketStyle = "userstyle";
const ticketStatus = "pending";
const newTicket = new Ticket({
body,
sender,
ticketStyle,
ticketStatus
});
newTicket
.save()
.then()
.catch(error => {
res.send(error);
});
});
I want add these posts to my collection, but since the "body" key-pair is required and I keep getting this error I'm stuck
Just figured the issue (clumsy mistake), this was due to an issue caused from how I decided to name my variables. I updated the schema and variable names and all worked as intended.
new route:
router.post("/", (req, res) => {
const sender = "admin";
const message = req.body.message;
const ticketStatus = "pending";
const ticketStyle = "userTicket";
const newTicket = new Ticket({
sender,
message,
ticketStyle,
ticketStatus
});
newTicket
.save()
.then(tickets => {
res.redirect(req.originalUrl);
console.log("Successfully saved to database");
})
.catch(err => {
res.status(400).send("unable to save to database");
console.log("unable to save to database");
});
});
And I also updated the schema name too.
const ticketSchema = new mongoose.Schema({
sender: {
type: String,
required: true
},
message: {
type: String,
required: true
},
ticketStatus: {
type: String
},
ticketStyle: {
type: String
},
reply: {
type: String
}
});
The issue was from requesting the body data in the route as just req.body, not req.body.message so I guess the code was trying to save/use the whole JSON file as a string (I guess) .

How do you save to three collections at once?

I'm building my first mean stack app. It's a review site that contains three models: User, Review, and Company.
When I make a review, I want the new review to be saved to the 'review' collection, and for that review to be connected by reference to the company being reviewed and the user who wrote the review. I also want the user to hold a reference to the review, and the company to hold a reference to all the reviews it has. Here are my models:
Review
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const reviewSchema = new Schema ({
companyName: String,
companyId: { type: Schema.Types.ObjectId, ref: 'Company'},
starRating: Number,
subject: String,
commentBody: String,
createdBy: { type: Schema.Types.ObjectId, ref: 'User'},
});
const Review = mongoose.model("Review", reviewSchema);
module.exports = Review;
Company
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const companySchema = new Schema ({
companyName: String,
about: String,
basedIn: String,
materialOrigins: [String],
productRange: [String],
category: String,
reviews: [ {type: Schema.Types.ObjectId, ref: 'Review'} ],
socialRating: Number,
environmentalRating: Number,
priceRange: Number
});
const Company = mongoose.model("Company", companySchema);
module.exports = Company;
User
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema ({
email: String,
firstName: String,
lastName: String,
password: String,
image: Object,
aboutText: String,
reviews: [ { type: Schema.Types.ObjectId, ref: "Review" } ]
// comments: { type: Schema.Types.ObjectId, ref: 'Comment' }
});
const User = mongoose.model("User", userSchema);
module.exports = User;
This is my current route, which currently saves the review to the collection and attaches the user. However, the user doesn't get the review.
route
router.post('/:category/:company', (req, res) => {
var subject = req.body.subject;
var commentBody = req.body.commentBody;
var starRating = req.body.starRating;
var userId = req.body.userId;
if(!subject || !commentBody || !starRating) {
res.status(400).json({ message: "Subject, comment body, and star rating are required." });
return;
}
var newReview = Review({
starRating,
subject,
commentBody,
userId
});
User.findById(userId, {
}, (err, user) => {
if (err) {
return res.send(err);
} else {
console.log("checking out user in route", user);
user.reviews.push(newReview);
user.save();
newReview.save((err, review) => {
if (err) {
return res.status(400).json({ message: err });
} else {
res.status(200).json({ message: 'Review saved', review });
}
});
}
});
I haven't tried adding the company in because I'm trying to do one thing at a time. I've been looking at 'populate', but all of the documentation seems to only use two models at once. Is it possible to do three at once? Or am I overcomplicating this?
Apologies if this is all overcomplicated. I'm fairly new to MongoDB and MEAN stack in general. Thanks for your help.
Ok, I did it, for any people landing on this page wondering the same thing in the future.
Here's my route:
router.post('/:category/:company', (req, res, next) => {
var companyName;
var companyId;
var subject = req.body.subject;
var commentBody = req.body.commentBody;
var starRating = req.body.starRating;
var createdBy = req.body.createdBy;
if(!subject || !commentBody || !starRating) {
res.status(400).json({ message: "Subject, comment body, and star rating are required." });
return;
}
var newReview = Review({
starRating,
subject,
commentBody,
createdBy
});
//I need the companyId and companyInfo for later use in my review save. I'm calling the company with the name I have from my params, and setting the id and name with the received data from Mongo.
Company.findOne({"companyName": req.params.company}, (err, company) => {
if (err) {
return res.status(400).json({ message: err });
} else {
this.companyName = company.companyName;
this.companyId = company.id;
}
});
newReview.save((err, review) => {
//Push the review id to the user
if (err) {
return res.status(400).json({ message: err });
} else { User.findByIdAndUpdate({_id: createdBy },{$push: {reviews: review.id} }, (err) => {
if (err) {
console.log("There was an error pushing review to user");
next(err);
//Push the review id to the company
} else { Company.findOneAndUpdate({ "companyName": req.params.company}, {$push: {reviews: review.id}}, (err, company) => {
if (err) {
console.log("There was an error pushing review to company");
next(err);
} else {
//Updates the review by setting companyId and companyName properties to review for Mongo
Review.update({_id: review.id}, {$set: {companyId: this.companyId, companyName: this.companyName}}, (err, changes) => {
if(err) {
return res.status(400).json({message : err});
} else {
console.log("updating review successfully with company info", changes);
}
});
console.log ("Review successfully saved");
res.json({
review: review,
});
}
});
}
});
}
});
});
If anyone has feedback on how this could be done better/more efficiently, let me know. Cheers.

Resources