I have my reportSchema.js which is where my schema is defined. I am storing the JSON I get back from the Microsoft Graph API into a variable called result. I want to store each value in the result array into mongodb. I am able to access individual items from the array like this
receivedDateTime: result.value[0].receivedDateTime,
sentDateTime: result.value[1].sentDateTime
But I want to be able to store everything at once. How can I go about doing this? I will post the code down below.
reportSchema
var mongoose = require('mongoose')
var sera = mongoose.Schema({
isRead: Boolean,
subject: String,
from: String,
receivedDateTime: Date,
sentDateTime: Date
});
module.exports = mongoose.model("SERA", sera)
sample of result array
value: [{
'#odata.etag': 'W/"CQAAAA=="',
id: 'AAMkADg4MTBkNmRiLTAwNzQtNDE1Ny1hNjlkLWVjNzE5N2M1MGEwMgBGAAAAAAA9yT6uaq2hTrV0L6GqHQ_CBwALVVFnK27cQ4tC6FzqOc3cAAAAAAEMAAALVVFnK27cQ4tC6FzqOc3cAANuNGz-AAA=',
receivedDateTime: '2019-03-09T03:45:45Z',
sentDateTime: '2019-03-09T03:45:44Z',
subject: 'Re: hw3',
isRead: true,
from: {
emailAddress: {
name: 'Example',
address: 'example.yahoo.com'
}
}
}]
how I am saving the report
SERA.insertMany(result.value, function (error, success) {
if (error) {
console.log("There has been an error inserting")
} else {
console.log("The API data has been stored")
}
})
// save stores into database
SERA.save().then(result => {
console.log(result)
}).catch(function (error) {
console.log("The error is " + error)
});
res.status(201).json({
message: "Handling post request to /api/report",
createdReport: report
});
You can use insertMany() it accepts array of values you want to save.
var mongoose = require('mongoose')
var sera = mongoose.Schema({
isRead: Boolean,
subject: String,
from: {
emailAddress: {
name: String,
address: String
}
},
receivedDateTime: Date,
sentDateTime: Date
});
const Sera = mongoose.model("SERA", sera)
const values = [{
id: 'AAMkADg4MTBkNmRiLTAwNzQtNDE1Ny1hNjlkLWVjNzE5N2M1MGEwMgBGAAAAAAA9yT6uaq2hTrV0L6GqHQ_CBwALVVFnK27cQ4tC6FzqOc3cAAAAAAEMAAALVVFnK27cQ4tC6FzqOc3cAANuNGz-AAA=',
receivedDateTime: '2019-03-09T03:45:45Z',
sentDateTime: '2019-03-09T03:45:44Z',
subject: 'Re: hw3',
isRead: true,
from: {
emailAddress: {
name: 'Example',
address: 'example.yahoo.com'
}
}
}]
Sera.insertMany(values, (error, docs) => {
if(error) {
console.log(error);
} else {
console.log(docs);
}
});
// alternative
// Sera.insertMany(values).then(docs => {
// console.log(docs)
// })
// .catch(error => {
// console.log(error)
// })
https://mongoosejs.com/docs/api.html#model_Model.insertMany
Related
I am trying to join two mongoose collection and fetch all related details using the query which i have mention below. Problem is I am getting only one table details employee collection not able get two collection detail when I call GetEmployeeDetails(emp_id) . Need a suggestion. How to get two collection data in one query.
const EmployeeInfoSchema = mongoose.Schema({
employee_id: String,
client_id: {
type: Schema.Types.Number,
ref: "client",
},
email: String,
contact: String,
});
const ClientInfoSchema = mongoose.Schema({
client_id: Number,
employee_id: {
type: Schema.Types.String,
ref: "employee",
},
project: String,
organization: String,
});
let employeeInfo = mongoose.model("employee", EmployeeInfoSchema);
let clientInfo = mongoose.model("client", ClientInfoSchema);
module.exports = { employeeInfo, clientInfo };
Query
async function GetEmployeeDetails(emp_id) {
let employee_info = await Storage.employeeInfo
.find()
.where({ employee_id: emp_id })
.populate({
path: "client",
})
.exec(function (err, block) {
if (err) {
console.log("%s", err);
}
console.log("Employee details is %s", employee_info);
});
return employee_info;
}
Try to change your GetEmployeeDetails method like this:
async function GetEmployeeDetails(emp_id) {
try {
let employee_info = await Storage.employeeInfo
.find({ employee_id: emp_id })
.populate('client')
.exec(function (err, block) {
if (err) console.log('%s', err);
else console.log('Employee details is %s', employee_info);
});
return employee_info;
} catch (err) {
res.status(400).send('Error getting details');
}
}
I am trying to create a followers/following function in my project. However I cannot seem to update the DB correctly. I'm able to send the ids as they both print when I console.log but nothing in my DB updates and I do not get any response in my frontend.
route
app.put('/api/follow', async function (req, res, next){
const { id } = req.query;
const userFrom = req.body.data
console.log('OTHER USER ID',id)
console.log('CURRENT ID', userFrom)
User.findByIdAndUpdate(id), {
$push:{followers:req.body.data}
},{new:true},
(err,result)=>{
if(err) {
if(err) return res.status(400).send(err)
}
User.findByIdAndUpdate(req.body.data), {
$push:{following:id}
},{new:true}.then(result=> {
res.json(result)
}).catch(err=>{
return res.status(422).json({error:err})
})
}
})
user model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
phoneNo: String,
bio: String,
filePath: String,
following: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
followers: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
module.exports = User;
my route end function
const clickHandler = () => {
const currentID = currentUser.id;
const id = this.props.id;
console.log('CURRENT ID',currentID)
console.log('otherUserID',id)
Axios.put(`http://localhost:8080/api/follow/?id=${id}`, { data: currentID }, { headers: authHeader() })
.then(response => {
if (response.data.success) {
console.log('FOLLOWED', response.data)
// this.setState({ userDetails: response.data.details })
} else {
alert('Error')
}
})
}
This should be
User.findByIdAndUpdate(id, {
You should not close the bracket after id but after new: true})
Working on a personal project, one of the functions of the project is to update the user status on what event they are participating.
i wanted to submit a value using a button
<form action="/users/fooddrivebanner" method="POST"><button name="fooddrive" type="submit" value="fooddrive" id="fooddrive">Participate</button></form>
then pass the value to my route and save it inside my database
router.post('/fooddrivebanner', (req,res)=>{
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
User.findOne({ _id: _id }).then((user)=>{
if (!user) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
if (typeof eventparticpating !== "undefined") {
user.eventparticpating = 'fooddrive';
}
user.save(function (err, resolve) {
if(err)
console.log('db error', err)
// saved!
});
})
.catch((err) => console.log(err));
Here is the User model
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
eventparticpating: {
type: String,
default: 'None At The Moment'
}
});
const User = mongoose.model('User', UserSchema);
module.exports = User;
It showed a console error
TypeError: Cannot set property 'eventparticpating' of null
UPDATE
Edit 1:
I followed Mr Gambino instructions, error Gone yet cannot update the database, how would i be able to adjust and find my user?
Instead of saving within the findOne function,you can do this:
router.post('/fooddrivebanner', async (req,res) => {
const { fooddrive } = req.body;
const _id = ObjectId(req.session.passport.user._id);
await User.findOne({ _id: _id }, (error, user) => {
if (error) {
req.flash("error_msg", "user not found");
res.redirect("/fooddrivebanner");
}
}).updateOne({ eventparticpating: "foodrive" });
});
I hope that answers your question
I have created a Mongo DB schema with Mongoose in Express.js and I am building the REST API. However when I try to update existing records the values that I do not update from the schema automatically become null. I understand why this happens just not sure exactly how it should be coded.
This is the route:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
{
$set: {
title: req.body.title,
project_alias: req.body.project_alias,
description: req.body.description
}
}
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
also here is the schema:
const ProjectsSchema = mongoose.Schema({
title: {
type: String,
required: true,
unique: true
},
project_alias: {
type: String,
unique: true,
required: true
},
description: String,
allowed_hours: Number,
hours_recorded: {
type: Number,
default: 0
},
date_added: {
type: Date,
default: Date.now
}
});
My problem is that when I want to update just the title:
{
"title" : "Title Updated33"
}
description and alias become null. Should I implement a check?
Just use req.body for the update object like this:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
req.body
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
Or even better, create a helper function like this so that we can exclude the fields in the body that doesn't exist in the model:
const filterObj = (obj, ...allowedFields) => {
const newObj = {};
Object.keys(obj).forEach(el => {
if (allowedFields.includes(el)) newObj[el] = obj[el];
});
return newObj;
};
router.patch("/:projectId", async (req, res) => {
const filteredBody = filterObj(
req.body,
"title",
"project_alias",
"description",
"allowed_hours",
"hours_recorded"
);
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
filteredBody
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
I want to make the key email unique across that collection but i cant getting this working, here is my server code.
// Create a schema
var userSchema = new mongoose.Schema({
email: { type: String, required: true},
password: String
});
var userModel = mongoose.model("user", userSchema);
router.post('/postuser', (req, res) => {
console.log('Requested data to server: ' + JSON.stringify(req.body._user));
var user = new userModel({
email: req.body._user.email,
password: req.body._user.password
});
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
})
});
Note: I also try email: { type: String, required: true, unique: true} but its not working and show below error.
name: 'MongoError',
message: 'E11000 duplicate key error collection: hutreservationsystem.users
index: _Email_1 dup key: { : null }',
driver: true,
code: 11000,
index: 0,
errmsg: 'E11000 duplicate key error collection: hutreservationsystem.users index: _Email_1 dup key: { : null }',
getOperation: [Function],
toJSON: [Function],
toString: [Function] }
A short answer using this tool mongoose-unique-validator
npm install --save mongoose-unique-validator
and in your model
var mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator')
var userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true},
password: String
});
userSchema.plugin(uniqueValidator)
var userModel = mongoose.model("user", userSchema);
That's it! (Notice unique: true)
Now, there is no email duplication in your collection.
Bonus! : you can access err
.catch(err => console.log(err))
so in your example
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
accessing err >>
so you can res.send(err.message) >> 'Validation failed'
{
message: 'Validation failed',
name: 'ValidationError',
errors: {
email: {
message: 'Error, expected `email` to be unique. Value: `example#gmail.com`',
name: 'ValidatorError',
kind: 'unique',
path: 'email',
value: 'example#gmail.com'
}
}
}
Async Custom Validator
var userSchema = new mongoose.Schema({
password: String,
email: {
type: String,
lowercase: true,
required: true,
validate: {
isAsync: true,
validator: function(value, isValid) {
const self = this;
return self.constructor.findOne({ email: value })
.exec(function(err, user){
if(err){
throw err;
}
else if(user) {
if(self.id === user.id) { // if finding and saving then it's valid even for existing email
return isValid(true);
}
return isValid(false);
}
else{
return isValid(true);
}
})
},
message: 'The email address is already taken!'
},
}
});
You may like to change the validator code to es6.
email: {
type: String,
trim: true,
unique: true, // note - this is a unqiue index - not a validation
validate: {
validator: function(value) {
const self = this;
const errorMsg = 'Email already in use!';
return new Promise((resolve, reject) => {
self.constructor.findOne({ email: value })
.then(model => model._id ? reject(new Error(errorMsg)) : resolve(true)) // if _id found then email already in use
.catch(err => resolve(true)) // make sure to check for db errors here
});
},
}
},
I implemented the following code to see if anything was wrong:
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var express = require('express');
var http = require('http');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
// Create a schema
var userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true},
password: String
});
var userModel = mongoose.model("user", userSchema);
app.post('/postuser', (req, res) => {
console.log('Requested data to server: ' + JSON.stringify(req.body._user));
var user = new userModel({
email: req.body._user.email,
password: req.body._user.password
});
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
})
});
http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000');
});
And I made sure that no collection by the name of users existed in my local MongoDB database. Moreover, I used Postman for sending API requests to my server at http://localhost:3000. There seemed to be no issue as I continued to add users with differing email values. And I only got the following error when I entered an email with a duplicate value
{
"code": 11000,
"index": 0,
"errmsg": "E11000 duplicate key error collection: test.users index: email_1 dup key: { : \"hot#mail.com\" }",
"op": {
"email": "hot#mail.com",
"password": "1234567",
"_id": "5919a3428c13271f6f6eab0f",
"__v": 0
}
}
These are the JSON requests that I sent:
{"_user": {"email": "hot#mail.com", "password": "1234"}}
{"_user": {"email": "sammy#mail.com", "password": "1234"}}
{"_user": {"email": "tommy#mail.com", "password": "1234"}}
{"_user": {"email": "tommy#mail.ae", "password": "1234567"}}
{"_user": {"email": "hot#mail.com", "password": "1234567"}}
The error mentioned above was sent back on the last request as the email hot#mail.com is repeated.
If you view the link http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique , you'll see that the E11000 error is only sent when the email entered is not unique. Moreover, your email can't be an empty string or not be present as that violates the required property.
ES6:
const userSchema = new Schema({
name: String,
id: {
type: String,
required: true,
unique: true,
validate: async (value) => {
try {
const result = await userModel.findOne({ id: value })
if (result) throw new Error("duplicity detected: id :" + value);
} catch (error) {
throw new Error(error);
}
}
}
})
const userModel = mongoose.model<Document>('users', userSchema);
ES6 (TypeScript):
const userSchema = new Schema({
name: String,
id: {
type: String,
required: true,
unique: true,
validate: async (value: any): Promise<any> => {
try {
const result: Document | null = await userModel.findOne({ id: value })
if (result) throw new Error("duplicity detected: id :" + value);
} catch (error) {
throw new Error(error);
}
}
}
})
const userModel: Model<Document, {}> = mongoose.model<Document>('users', userSchema);
In your user schema set attribute email as unique (unique: true).
var userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true}, });