I have problem to insert a value inside an array using node.js and mongodb
1). MongoDb Schema
var userScore = new Schema({
child: {
quiz_level: {
current_level: {type:Number},
level_attempted: {
type: Array,
level_id: {type:Number},
level_complete: {type:Boolean},
level_score: {type:Number}
}
}
}
});
2). Node js
try{
// var quiz = levelScoreQuiz.child;
var userObj = {
"child.quiz_level.level_attempted.level_score": req.body.score
};
var user = new levelScoreQuiz(userObj);
user.save(function(err, result){
if (err) {
console.log('Error While Saving the reuslt ' +err)
} else {
console.log("User score saved successfully");
res.json(result);
}
});
} catch(err){
console.log('Error While Saving the reuslt ' +err);
return next(err);
}
3). Json result
This will shows the empty result of array insertions
{
"__v": 0,
"_id": "57832f610118546713d23466",
"child": {
"quiz_level": {
"level_attempted": [] //This is the empty array
}
}
}
Related
I am learning mongoose and I'm unable to understand some code execution order of javascript
Code:
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost:27017/fruitsDB");
const fruitSchema = new mongoose.Schema({
name: {
type: String,
required: [true, "Please check your data entry, no name specified!"],
},
rating: {
type: Number,
min: 1,
max: 10,
},
review: String,
});
const Fruit = mongoose.model("Fruit", fruitSchema);
// Reading data from database
Fruit.find((err, fruits) => {
if (err) {
console.log(err);
} else {
// console.log(fruits);
mongoose.connection.close();
fruits.forEach((fruit) => {
console.log(fruit.name);
});
}
});
// Updating data in database
Fruit.updateOne({ name: "Kiwi" }, { name: "Peach" }, (err) => {
if (err) {
console.log(err);
}
else {
console.log("Successfully updated data");
}
});
// Deleting data in database
Fruit.deleteOne({ name: 'Peach' }, (err) => {
if (err) {
console.log(err);
}
else {
console.log('Data deleted successfully');
}
})
console.log output:
I am unable to understand why the Update function in running before the find() function, can anyone explain this to me please?
Hi everyone I am new to mysql and would like to test if the same genre exist in a database and if it does it returns a status code and if the genre does not exist the genre is added into the database. I am currently having the following issues, it is able to check if the genre exist and return the status code but when entering a different genre it reacts the same way as if the genre exist :
file 1
Insertgenre:function(genre,description,callback){
var dbConn=db.getConnection();
// connects to the mysql database (contains an asyn function that returns a callback)
dbConn.connect(function(err){
if(err){
console.log(err);
return callback(err,result);
}else{
// Query for get all rows from genre table where genre = entered genre
var checkSql = 'SELECT genre FROM genre WHERE genre = ?';
dbConn.query(checkSql, [genre], function(err1, result) {
if(err) {
return callback(err,result);
}else {
// Checking if the result length is more than 0.
if(result.length > 0) {
return callback(err1,result);
}else {
var sql="insert into genre(genre,description) values(?,?)";
dbConn.query(sql,[genre,description],function(err,result){
dbConn.end();
if(err) {
console.log(err);
}
return callback(err,result);
}
}
}
});
file 2
app.post('/genre', function(req,res){
var genre = req.body.genre;
var description = req.body.description;
genreDB.Insertgenre(genre,description,function(err,err1,result){
if(err){
//console.log(err)
res.type('json');
res.statusCode=500;
res.send(`{"Result":"Internal Error"}`);
}if(err1){
console.log(err1)
res.type('json');
res.statusCode=422;
res.send(`{"Result":"The genre name provided already exists"}`);
}
else{
res.type("json");
res.statusCode=204;
//res.send(result);
console.log(result);
res.send(`{"Affected Rows":"${result.affectedRows}"}`);
}
});
});
Your callback function expects err to be a normal database error, and err1 to indicate that the genre already exists.
You need to call callback() with 3 arguments to match what it expects.
You also have a typo. In the second query, the callback function's argument is err1, but you used if(err).
And in file 2, you should use else if(err1) since all these conditions are mutually exclusive.
Insertgenre: function(genre, description, callback) {
var dbConn = db.getConnection();
// connects to the mysql database (contains an asyn function that returns a callback)
dbConn.connect(function(err) {
if (err) {
console.log(err);
return callback(err, false, result);
} else {
// Query for get all rows from genre table where genre = entered genre
var checkSql = 'SELECT genre FROM genre WHERE genre = ?';
dbConn.query(checkSql, [genre], function(err1, result) {
if (err1) {
return callback(err1, false, result);
} else {
// Checking if the result length is more than 0.
if (result.length > 0) {
return callback(null, true, result);
} else {
var sql = "insert into genre(genre,description) values(?,?)";
dbConn.query(sql, [genre, description], function(err, result) {
dbConn.end();
if (err) {
console.log(err);
}
return callback(err, false, result);
}
}
}
});
});
})
This loop is supposed to be checking for opps in the DB that match opps being pulled from the salesforce api results and then either creating a new opp or finding the existing opp and pushing it to the array. It seems that the res.render is running before the opp is found. It creates a new opp but the array returns empty when the page renders.
Account.find({owner:req.user._id, prospect:'false'}).sort({ammount:'desc'}).populate({path: "notes", options:{ sort:{ 'date': -1 } } }).exec(function(err, allAccounts) {
let callGoal = req.user.callGoal;
if(err){
res.send(err);
}else{
// if auth has not been set, redirect to index
if (!req.session.accessToken || !req.session.instanceUrl) { res.redirect('/'); }
//SOQL query
let q = "SELECT Id,Amount,CloseDate,LastActivityDate,Name,StageName,account.Name FROM Opportunity WHERE CloseDate < 2018-10-01 AND OwnerId = '0050a00000J12PdAAJ' AND IsClosed = false AND StageName != 'Stage 6: Won'";
//instantiate connection
let conn = new jsforce.Connection({
oauth2 : {oauth2},
accessToken: req.session.accessToken,
instanceUrl: req.session.instanceUrl
});
//set records array
let softopps = [];
let sfOpps = [];
let query = conn.query(q)
.on("record", function(record) {
sfOpps.push(record);
})
.on("end", function() {
console.log("total in database : " + query.totalSize);
console.log("total fetched : " + query.totalFetched);
let user = req.user;
sfOpps.forEach(function(sfopp){
if(err){
res.send(err);
}else{
Opp.findOne({sfid:sfopp.Id}).exec(function(err, opp){
if(!opp.length){
Opp.create(req.body, function(err, newOpp) {
if(err){
res.send(err)
}else{
newOpp.sfid = sfopp.Id;
newOpp.name = sfopp.Name;
newOpp.owner = user.sfid;
newOpp.save();
return softopps.push(newOpp)
}
})
}else{
return softopps.push(opp);
}
})
}
})
res.render("myaccounts", {accounts:allAccounts, callGoal:callGoal, user:user, sfOpps:sfOpps, opps:softopps});
})
.on("error", function(err) {
console.error(err);
})
.run({ autoFetch : true, maxFetch : 4000 });
}
});
Your Opp.findOne() and Opp.create() calls are asynchronous, so they fire after the res.render().
On the side, you pretty much kill your mongodb with all that unnecessary requests.
Try this logic instead (starting at .forEach)
Find all Opps by ids of sfOpps
Figure out which Opps were not found and create them
Concat all the found and not found Opps
Then, and only then respond
I didn't test that code, but it can roughly give you an idea of what I mean
Opp.find({ sfid : { $in: sfOpps.map(opp => opp.id) } })
.then(found => {
const foundIds = found.map(opp => opp.sfid)
const notFound = sfOpps.filter(opp => !foundIds.includes(opp.sfid)).map(sfopp => {
return {
sfid: sfopp.sfid,
name: sfopp.name,
owner: user.sfid
}
})
Opp.insertMany(notFound)
.then((insertResult) => {
res.render("myaccounts", {
accounts: allAccounts,
callGoal: callGoal,
user: user,
sfOpps: found.concat(notFound),
opps: softopps
});
}).catch(handleError)
}).catch(handleError)
When the page rendered your still empty because the call of creation/find opps is an asynchronous but your page rendering is synchronous that's why your page rendered first before your calls will be complete.I think you should try to use async.eachOfSeries(coll, iteratee, callback) instead of sfOpps.forEach().
Account.find({owner:req.user._id, prospect:'false'}).sort({ammount:'desc'}).populate({path: "notes", options:{ sort:{ 'date': -1 } } }).exec(function(err, allAccounts) {
let callGoal = req.user.callGoal;
if(err){
res.send(err);
}else{
// if auth has not been set, redirect to index
if (!req.session.accessToken || !req.session.instanceUrl) { res.redirect('/'); }
//SOQL query
let q = "SELECT Id,Amount,CloseDate,LastActivityDate,Name,StageName,account.Name FROM Opportunity WHERE CloseDate < 2018-10-01 AND OwnerId = '0050a00000J12PdAAJ' AND IsClosed = false AND StageName != 'Stage 6: Won'";
//instantiate connection
let conn = new jsforce.Connection({
oauth2 : {oauth2},
accessToken: req.session.accessToken,
instanceUrl: req.session.instanceUrl
});
//set records array
let softopps = [];
let sfOpps = [];
let query = conn.query(q)
.on("record", function(record) {
sfOpps.push(record);
})
.on("end", function() {
console.log("total in database : " + query.totalSize);
console.log("total fetched : " + query.totalFetched);
let user = req.user;
async.eachOfSeries(sfOpps,function(sfopp,next){
if(err){
next(err);
}else{
Opp.findOne({sfid:sfopp.Id}).exec(function(err, opp){
if(!opp.length){
Opp.create(req.body, function(err, newOpp) {
if(err){
next(err);
}else{
newOpp.sfid = sfopp.Id;
newOpp.name = sfopp.Name;
newOpp.owner = user.sfid;
newOpp.save();
softopps.push(newOpp);
next();
}
})
}else{
softopps.push(opp);
next();
}
})
}
},function(err){
if (err) res.send(err);
else {
res.render("myaccounts", {accounts:allAccounts, callGoal:callGoal, user:user, sfOpps:sfOpps, opps:softopps});
}
});
})
.on("error", function(err) {
console.error(err);
})
.run({ autoFetch : true, maxFetch : 4000 });
}
});
I hope this will help you.
So i have implemented a mongodb on my nodejs server. And what I have done is store users via:
function insertUser() {
var collection = dbb.collection('user');
var user1 = {name: user, token: token};
collection.insert(user1, function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
}
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
So result will equal:
Found: [ { _id: 57be1cadc281c03ea116c9ab,
name: 'Austin Hunter',
token: 'dJyXVjMJk08kXWrua8SUjKb....SxACihKZoR53y_wOZmcFNKMmD5q99QNvsp3flL' } ]
My question is, how can I get that token out to equal selectedUserToken so I can send a push notification with gcm? Right now result.token is undefined.
You should use findOne() instead of find() since you only expect a single result back:
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.findOne({name: devName}, function (err, result) {
if (err) {
console.log(err);
} else if (result) {
console.log('Found: ', result);
selectedUserToken = result.token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
But if you wanted to leave your code as is with the find() you would just retrieve the first element of the resulting array retrieved by find()
function findUserByName(devName) {
var collection = dbb.collection('user');
collection.find({name: devName}).toArray(function (err, result) {
if (err) {
console.log(err);
} else if (result.length) {
console.log('Found: ', result);
selectedUserToken = result[0].token;
} else {
console.log('No document found');
insertUser();
}
dbb.close();
});
}
Maybe result[0].token, because result is an array of user items.
I have to try to store array data inside MongoDB using this query below. but every time I run this query its show success message without data means an empty array inside MongoDB,
my requirement is to store array data inside MongoDB as below query.
1). This is my node js script
this.childQuestionInfo = function(req, res, next){
try{
var quizArr = [];
var quizObj = {
'child.quiz.questionId' : req.params.questionId,
'child.quiz.score' : req.params.score,
'child.quiz.time' : new Date().toISOString()
};
quizArr.push(quizObj);
var userObj = {
'userid' : req.params.userId,
'quiz' : quizArr
};
var childinfoSave = new QuizChildInfo(userObj);
childinfoSave.save(function(err, data){
if(err) return next(err);
res.send("Child questionId score and date saved successfully" + data);
console.log("Child questionId score and date saved successfully");
});
}catch(err){
console.log('Error While Saving the child questionId score and Date ' +err);
return next(err);
}
};
2). This is my child schema
userId:{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
quiz:[
{
questionId:{
type: mongoose.Schema.Types.ObjectId,
ref: 'question'
},
score:{type:Number},
time:{type:String}
}
]
3). This is my output screen via postman
"Child questionId score and date saved successfully
{ __v: 0,\n _id: 57b9ac672c5791f8097d2132,\n levelsAttempted: [],\n quiz: [ { _id: 57b9ac672c5791f8097d2133 } ] }"
Try this using $push
this.childQuestionInfo = function(req, res, next){
try{
var queryObj={};
var childObj={};
var queryObj = {userid: req.params.userId};
var options = {safe: true, upsert: true};
childObj.questionId' : req.params.questionId,
childObj.score' : req.params.score,
childObj.time' : new Date().toISOString()
};
QuizChildInfo.findOneAndUpdate( queryObj, { $push: childObj }, options, function (err, data) {
if(err) return next(err);
res.send("Child questionId score and date saved successfully" + data);
console.log("Child questionId score and date saved successfully");
});
}catch(err){
console.log('Error While Saving the child questionId score and Date ' +err);
return next(err);
}
};