Related
I have a User model and trying to add education field to mongoDB as json object as follows,
User model
education: {
"school": String,
"years":Number
},
Client
//add Education section
const updateEducation = async (e) => {
e.preventDefault();
await fetch(`http://localhost:5000/api/user/updateEducation`, {
method: "PUT",
headers: { "Content-Type": "application/JSON", token: accessToken },
body: JSON.stringify({ userid: userid, educationSchool: educationSchool,
educationYearText: EducationYear}),
})
.then((res) => res.json())
.then((data) => {
console.log("User education is:", data.education +""+data.educationYear);
});
};
Server
const updateEducation = async (req, res) => {
try {
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{
$set: {
'education.school': req.body.educationSchool,
'education.years': req.body.educationYearText,
},
}
);
if (!user) {
res.status(404).json("user not exist");
}
res
.status(200)
.json({
education: user.education.School,
educationYear: user.education.years,
});
} catch (error) {
res.status(500).send({ error: error.message });
}
};
When im hitting this endpoint in postman http://localhost:5000/api/user/updateEducation
{
"userid":"63bbe4df75dca5aac7576e47",
"educationSchool":"Test college",
"educationYearText":"2018"
}
Im getting {
"error": "Plan executor error during findAndModify :: caused by :: Cannot create field 'school' in element {education: []}"
}
Whats wrong?
You should $push into an array:
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{
$push: {
education: {
school: req.body.educationSchool,
years: req.body.educationYearText,
}
},
},
{ new: true }
);
I am new in the relational database. I am using node js and express for the backend, REST API and database is Postgresql. I am using Sequelize for connection and models.I have created two models, one is a student and another is a course. My goal is One student can have multiple courses and want to prevent duplicate student name, phone, email. I successfully connect to the database and able to post,get,update, delete the both student and course model. From testing the app I am using Postman. But I am not sure, am I doing right for the relationship between student and course. And also I don't how to display the relationship between two tables. I will be really glad if anyone helps me out.
I want to display my like this:
{
"students": [
{
"id": 1,
"name": "Anni Anonen",
"birthday": "1992-02-28",
"address": "Kivakatu 1",
"zipcode": "00500",
"city": "Helsinki",
"phone": "+358506760702",
"email": "anni.anonen#testing.fi",
"courses": [1,2,3] //SHOW COURSES LIKE THIS
},
{
"id": 2,
"name": "Ville Anonen",
"birthday": "2000-03-28",
"address": "Hämeentie 1",
"zipcode": "00510",
"city": "Helsinki",
"phone": "+358508660702",
"email": "ville.anonen#testing.fi",
"courses": [3]
},
{
"id": 3,
"name": "Tapani Kumpu",
"birthday": "1999-05-28",
"address": "Jokukatu 17",
"zipcode": "00560",
"city": "Helsinki",
"phone": "+358502330702",
"email": "tapani.kumpu#testing.fi",
"courses": [1,4]
}
],
"courses": [
{
"id": 1,
"name": "Gymnastics 1",
"startdate": "2020-01-01",
"enddate": "2020-02-10"
},
{
"id": 2,
"name": "Gymnastics 2",
"startdate": "2020-01-01",
"enddate": "2020-02-10"
},
{
"id": 3,
"name": "Fitness 1",
"startdate": "2020-02-01",
"enddate": "2020-02-20"
},
{
"id": 4,
"name": "Dance 1",
"startdate": "2020-05-01",
"enddate": "2020-05-02"
}
]
}
This is my models
const sequelize = require("sequelize");
var con = new sequelize("school", "postgres", "password", {
host: "localhost",
dialect: "postgres",
pool: {
max: 5,
min: 0,
idle: 10000
}
});
const Student = con.define("student", {
name: {
type: sequelize.STRING,
allowNull: false
},
birthday: {
type: sequelize.DATEONLY,
allowNull: false
},
address: {
type: sequelize.STRING,
allowNull: false
},
zipcode: {
type: sequelize.INTEGER,
allowNull: false
},
city: {
type: sequelize.STRING,
allowNull: false
},
phone: {
type: sequelize.BIGINT,
allowNull: false
},
email: {
type: sequelize.STRING,
allowNull: false,
validate: {
isEmail: true
}
}
});
const Course = con.define("course", {
id: {
type: sequelize.INTEGER,
primaryKey: true
},
name: { type: sequelize.STRING },
startdate: { type: sequelize.DATEONLY },
enddate: { type: sequelize.DATEONLY },
studentId: { type: sequelize.INTEGER, foreignKey: true }
});
Student.hasMany(Course);
Course.belongsTo(Student);
//con.sync({ force: true });
module.exports = { Student, Course };
This is express server
require("dotenv").config();
const express = require("express");
const app = express();
const morgan = require("morgan");
const helmet = require("helmet");
const cors = require("cors");
const { Student, Course } = require("./db");
//app middlewear
app.use(morgan("common"));
app.use(helmet());
app.use(cors());
app.use(express.json()); //body Parser
//student
app.get("/students", async (req, res, next) => {
try {
await Student.findAll().then(docs => {
const response = {
count: docs.length,
students: docs
};
res.json(response);
});
} catch (error) {
console.log(error);
}
});
app.get("/students/:id", async (req, res, next) => {
const id = req.params.id;
try {
Student.findByPk(id).then(data => {
console.log(data);
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.put("/students/:id", async (req, res) => {
const id = req.params.id;
const update = req.body;
try {
await Student.update(update, { where: { id } }).then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.delete("/students/:id", async (req, res, next) => {
const id = req.params.id;
try {
Student.destroy({ where: { id } }).then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.post("/students", async (req, res, next) => {
try {
const logs = new Student(req.body);
const entry = await logs.save();
res.json(entry);
} catch (error) {
if (error.name === "ValidationError") {
res.status(422);
}
next(error);
}
});
//course
app.get("/courses", async (req, res, next) => {
try {
await Course.findAll().then(docs => {
const response = {
count: docs.length,
courses: docs
};
res.json(response);
});
} catch (error) {
console.log(error);
}
});
app.get("/courses/:id", async (req, res, next) => {
const id = req.params.id;
try {
Course.findByPk(id).then(data => {
console.log(data);
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.put("/courses/:id", async (req, res, next) => {
const id = req.params.id;
const update = req.body;
try {
await Course.update(update, { where: { id } }).then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.delete("/courses/:id", async (req, res, next) => {
const id = req.params.id;
try {
Course.destroy({ where: { id } }).then(data => {
res.json(data);
});
} catch (error) {
console.log(error);
}
});
app.post("/courses", async (req, res, next) => {
try {
const logs = new Course(req.body);
const entry = await logs.save();
res.json(entry);
} catch (error) {
if (error.name === "ValidationError") {
res.status(422);
}
next(error);
}
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`🚀 App is listening at port ${port}!`));
I'm trying to create models with including related models. Then validation is failed i get only 1 error instead of all fails of validation.
at example is
[
{
"loads": {
"name": "Name is required"
}
}
]
How can i get all validation fails with all related models? Like
[
{
"model1": {
"name": "Name is required"
}
},
{
"model2": {
"name": "Name is required"
}
},
{
"model3": {
"name": "Name is required"
}
},
{
"etc": {
"name": "Name is required"
}
}
]
Here is my router function:
router.post('/', [checkAuth], async (req, res) => {
let {
name="",
weight="",
volume="",
packing_type="",
price_request="",
note="",
visible="",
Origin={city_id: '', date_from: ''}, // Origin object
Destination={city_id: ''}, // Destination object
} = req.body;
result = await db.transaction((t) => {
return LoadModel.create({
user_id: user_id,
name: name,
weight: weight,
volume: volume,
packing_type: packing_type,
price_request: price_request,
note: note,
visible: visible,
origin: Origin,
destination: Destination,
},{ include: [
OriginModel, DestinationModel
], transaction: t})
}).then(result => {
res.status(201).json(result);
}).catch(Sequelize.ValidationError, (err) => {
res.status(400).json(err.errors.map(item => {
return {
[item.instance._modelOptions.tableName]: {[item.path]: item.message}
};
})); // How can i get all validation errors for returning it?
}).catch(badError => {
res.status(500).json(badError);
})
validateErrors.catch(err => {
console.log(err);
})
});
Maybe there is a way to return validation errors from promise to global object? Or something else...
I've got a relational json called "client" inside Bill's model. This is my code:
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", required: true },
detail: [
{
quantity: Number,
product: { code: Number, name: String, price: Number },
undertotal: Number
}
],
total: Number
});
mongoose.model("bills", billSchema);
this is my post route:
app.post("/api/bills", async (req, res) => {
const { number, type, local, client, detail, total } = req.body;
await Client.findById(req.body.client._id).then(client => {
if (!client) {
return res.status(404).json({
message: "client not found"
});
}
});
const bill = new Bill({
number,
date: new Date(),
type,
local,
client,
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);
}
res.status(500).send(err);
}
});
//my get route
app.get("/api/bills", function(req, res) {
Bill.find({}, function(err, bills) {
Client.populate(bills, { path: "clients" }, function(err, bills) {
res.status(200).send(bills);
});
});
});
I want something like this:
{
"number": 302,
"type": "c",
"local": "porstmouth",
"client": {
"address": {
"street": "victoria street",
"number": 1001,
"floor": "2",
"flat": 4
},
"_id": "5dab929613fb682b48e4ca6b",
"name": "luke skywalker",
"mail": "l.skywalker#yahoo.com",
"cuil": "39193219",
"phone": 128391,
"__v": 0
},
"detail": [
{
"quantity": 500,
"product": {
"code": 300,
"name": "P2",
"price": 800
},
"undertotal": 5000
}
],
"total": 11000
}
But I see this result:
{
"date": "2019-10-20T12:27:17.162Z",
"_id": "5dac52a577e09b4acc45718d",
"number": 302,
"type": "c",
"local": "porstmouth ",
"client": "5dab929613fb682b48e4ca6b",
"detail": [
{
"_id": "5dac52a577e09b4acc45718e",
"quantity": 500,
"product": {
"code": 300,
"name": "P2",
"price": 800
},
"undertotal": 5000
}
],
"total": 11000,
"__v": 0
}
I don't want to see id client only. I want to see all content from client inside bill.
I tried to do with populate method, but I haven't results.
So, Which is form to post and populate a nested json relational object in this case?
While posting only clientId is enough.
So your post route can be like this (you both used await and then, which is incorrect, so I refactored it to use only await)
app.post('/api/bills', async (req, res) => {
const { number, type, local, client, detail, total } = req.body;
let existingClient = await Client.findById(req.body.client._id)
if (!existingClient) {
return res.status(404).json({
message: "client not found"
});
}
const bill = new Bill({
number,
date: new Date(),
type,
local,
client: req.body.client._id
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);
}
res.status(500).send(err);
}
});
And in the get route to retrieve all the client info you need to populate it like this:
app.get('/api/bills', async (req, res) => {
try {
const bills = await Bill.find({}).populate("clients");
res.status(200).send(bills);
} catch (err) {
console.log(err);
res.status(500).send(err);
}
}
)
I want to rename the path of the fields which are coming from the response.
My Query:
const allLeads = await Lead.find().select({
"basic.mobileNumber": 1
});
res.send({ allLeads });
Response I'm Getting
{
"allLeads": [
{
"_id": "5d9f0e2118d1a445bae077aa",
"basic": {
"mobileNumber": "1223654789"
}
},
{
"_id": "5d9f16a8cba7744902acb422",
"basic": {
"mobileNumber": "1123654789"
}
}
]
}
how I want the response
{
_id: 5d9f0e2118d1a445bae077aa,
mobileNumber: "1223654789"
},
{
_id: 5d9f16a8cba7744902acb422,
mobileNumber: "1123654789"
}
So is there any way yo archive this using mongoose?
I did it like this. Is there any other and better way to do this?
let simpleLeadInfo = [];
await SwatiLead.find()
.select({
_id: 1,
"basic.mobileNumber": 1,
})
.exec((err, data) => {
if (!err) {
for (lead in data) {
const obj = {
id: data[lead]._id,
mobileNumber: data[lead].basic.mobileNumber,
};
simpleLeadInfo = [...simpleLeadInfo, obj];
}
return res.send({ error: false, status: "OK", simpleLeadInfo });
}
});