model.update() not updating - node.js

I'm trying to add a new element to an array.
This is the code:
var findEditThenSave = function(personId, done) {
var foodToAdd = 'hamburger';
var foodArray = [];
Person.findById(personId, function (err, data) {
if (err) return console.log(err);
done(null, data);
foodArray = data.favoriteFoods;
console.log("foodArray inside findById: ", foodArray);
foodArray.push(foodToAdd);
var updateObj = {favoriteFoods: foodArray};
console.log(updateObj)
Person.update({_id: personId}, updateObj, function(err, raw) {
if (err) {
console.log("There was an error");
}
console.log("Updated successfully");
console.log("foodArray inside update function:", foodArray);
});
});
};
This is the whole code on Glitch: https://glitch.com/edit/#!/holly-maroon-pony?path=myApp.js%3A226%3A0
This is the console log for a POST request:
POST
foodArray inside findById: ["spaghetti"]
{ favoriteFoods: ["spaghetti","hamburger"] }
(node:8943) DeprecationWarning: collection.update is deprecated. Use updateOne, updateMany, or bulkWrite instead.
Updated successfully
foodArray inside update function: ["spaghetti","hamburger"]

You can use async and await while making these updates.
var findEditThenSave = async function(personId, done){
var foodToAdd = 'hamburger';
var foodArray = [];
var updateObj;
try{
var data=await Person.findById(personId);
done(null, data);
foodArray = data.favoriteFoods;
console.log("foodArray inside findById: ", foodArray);
foodArray.push(foodToAdd);
updateObj = {favoriteFoods: foodArray};
console.log(updateObj)
}catch(err){
console.log(err);
}
try{
await Person.update({_id: personId}, updateObj);
console.log("Updated successfully");
console.log("foodArray inside update function:", foodArray);
}catch(err){
console.log(err);
}
};

As you can see in your console:
(node:8943) DeprecationWarning: collection.update is
deprecated. Use updateOne, updateMany, or bulkWrite instead.
Updated successfully
So you can get through this using Person.updateOne instead of Person.update
Hope it helps

If you are just planning to update a document and return the updated document you can do something like this
function update(personId) {
var foodToAdd = "hamburger";
const person = Person.findByIdAndUpdate(
personId,
{ $push: { favoriteFoods: foodToAdd } },
{ new: true },
function (err, result) {
if (err) console.log(err);
else console.log(result);
}
);
};

Related

Not able to return value from promise in Nodejs

I have written the following code in Nodejs which is saving data in MongoDB:
function insertDoc(db,data){
return new Promise(resolve => {
callback=db.collection('AnalysisCollection').insertOne(data).then(function(response,obj){
console.log("Inserted record");
resolve(obj);
//console.log(obj);
// response.on('end',function(){
// resolve(obj);
// });
//return resolve(obj);
}).then(() => { return obj }
).catch(function(error){
throw new Error(error);
});
})
}
I am calling the above function from the main function like this:
async function cosmosDBConnect(nluResultJSON){
try{
//console.log("Inserting to cosmos DB");
console.log(nluResultJSON);
var url = config.cosmos_endpoint;
var result="";
var data = JSON.parse(JSON.stringify(nluResultJSON));
MongoClient.connect(url, function(err, client) {
assert.equal(null, err);
var db = client.db('NLUAnalysisDB');
// insertDoc(db, data, function() {
result=insertDoc(db, data, function() {
console.log(result);
client.close();
//return data._id;
});
});
}
catch (e) {
console.log(e);
}
}
module.exports = { cosmosDBConnect };
But in cosmosDBConnect, I am getting 'undefined' for the result, though in insertDoc I am getting the output for'obj' with _id for the inserted record.
Please help me to return this _id to cosmosDBConnect.
You are use callbacks inside of async function, which creates internal scopes. So your return aplies to them instead of whole function. You should use Promise-based methods inside of async function using await (without callbacks) or wrap whole function into own Promise otherwise.
Example:
function cosmosDBConnect(nluResultJSON) {
return new Promise((resolve, reject) => {
var url = config.cosmos_endpoint;
var result = '';
var data = JSON.parse(JSON.stringify(nluResultJSON));
MongoClient.connect(url, function(err, client) {
if (err) return reject(err);
assert.equal(null, err);
var db = client.db('NLUAnalysisDB');
insertDoc(db, data).then(obj => {
console.log(obj);
client.close();
return resolve(data._id);
});
});
});
}
Also you need to understand that your insertDoc return Promise and do not accept callback you tried to pass.
Ref: async function
result = insertDoc(db, data).then((data) => {
console.log(data);
}).catch(err => console.error(err));

Mongoose .select is not a function when using with Azure Function

I'm trying to use mongoose .select operator with my azure function but it keeps saying TypeError: db.collection(...).findOne(...).select is not a function at db.collection.find.toArray
It returns the user's data in the console, but doesn't filter it down with .select
Why is that?
var MongoClient = require('mongodb').MongoClient;
var Post = require('./model/post');
var mongoose = require('mongoose');
module.exports = async function (context, req) {
let currentPage = 1;
MongoClient.connect(process.env.CosmosDBConnectionString, async (err, client) => {
let send = response(client, context);
if (err) send(500, err.message);
let db = client.db(process.env.dbName);
await db.collection('listings').find(
{
$and: [
{ winnerHasBeenNotified: false },
{ auctionEndDateTime: { $lte: Date.now().toString() } }
]
}
)
.toArray((err, result) => {
console.log("result");
console.log(result);
if (result) {
for (let i = 0; i < result.length; i++) {
db.collection('users').findOne(
{
_id: mongoose.Types.ObjectId(result[i].bidderId)
}
).select("notificationBy").toArray((err, result) => {
console.log("USER RESULT!");
console.log(result);
});
}
}
if (err) send(500, err.message);
send(200, JSON.parse(JSON.stringify(result)));
});
});
};
function response(client, context) {
return function (status, body) {
context.res = {
status: status,
body: body
};
client.close();
context.done();
};
}
find() returns a cursor, which has a select method. findOne() retrieves a single document and returns a promise if no callback is provided.
If you are trying to get just the "notificationBy" field, try passing the fields option to findOne.

Improve code with a Promise for a mongodb request

I'm new to javascript (and coding) and I'm looking into Promises.
I have the following working code:
router.get("/test", function(req, res){
var mainCategory = new Promise(function(resolve, reject){
Maincategory.find().populate("subcategory").exec(function(err, allMaincategories){
if (err) {
console.log("error 1");
reject("error 2");
}
else {
resolve(allMaincategories);
}
});
});
var itemQuery = new Promise(function(resolve, reject){
Items.find({}, function(err, allItems){
if (err) {
console.log("error 3");
reject("error 4");}
else {
resolve(allItems);
reject("error 5");
}
});
});
Promise.all([
mainCategory,
itemQuery
]).then(function(allQueries){
console.log(allQueries);
var allCategories = allQueries[0];
var allItems = allQueries[1]
var userId = "true";
var show = "list";
res.render("test.ejs", {
allCategories: allCategories,
allItems: allItems,
userId: userId,
show: show
});
}).catch(function(error){
console.log("error 6");
res.render("error.ejs", {error: error});
});
});
Question 1: Is it correct to use a callback inside a promise like that?
Question 2: Is there a (shorter) way to put all mongoose requests in one promise?
Mongoose queries return Promises already - since you're using Promises, better to just use the Promise it returns rather than to construct a new one to use with the callback:
Promise.all([
Maincategory.find().populate("subcategory").exec(),
Items.find({})
]).then(function(allQueries){
// ...
mongoose already supports promises natively, so there's no reason at all to create a promise like you are doing. This:
var mainCategory = new Promise(function(resolve, reject){
Maincategory.find().populate("subcategory").exec(function(err, allMaincategories){
if (err) {
console.log("error 1");
reject("error 2");
}
else {
resolve(allMaincategories);
}
});
});
should be replaced with
const subcatPromise = Maincategory.find().populate("subcategory").exec();
and
var itemQuery = new Promise(function(resolve, reject){
Items.find({}, function(err, allItems){
if (err) {
console.log("error 3");
reject("error 4");}
else {
resolve(allItems);
reject("error 5");
}
});
});
is equivalent to
const itemsPromise = Items.find({});
router.get("/test", async function (req, res) {
try {
const allQueries = await Promise.all([Maincategory.find().populate("subcategory").exec(), Items.find({}).exec()]),
allCategories = allQueries[0],
allItems = allQueries[1],
userId = "true",
show = "list";
res.render("test.ejs", {
allCategories: allCategories,
allItems: allItems,
userId: userId,
show: show
});
} catch (error) {
console.log("error 6");
res.render("error.ejs", {
error: error
});
};
});

Botpress - how to bring database values into the chat window?

I'm trying to build a chatbot using Botpress. I'm a beginner, looking for your help. One of the requirements is to query database to answer questions. This is what I have tried so far:
dbconnect.js
var oracledb = require('oracledb');
var dbConfig = require('./dbconfig.js');
var db = function dbCall(sql, values) {
return new Promise(function(resolve, reject){
oracledb.getConnection(
{
user : dbConfig.user,
password : dbConfig.password,
connectString : dbConfig.connectString
},
function(err, connection) {
if (err) {
reject(err);
return;
}
connection.execute(
sql,
values,
{
maxRows: 1
},
function(err, result) {
if (err) {
console.error(err.message);
return;
}
resolve(result);
doRelease(connection);
}
);
});
});
}
// Note: connections should always be released when not needed
function doRelease(connection) {
connection.close(
function (err) {
if (err) {
console.error(err.message);
}
});
}
module.exports = db;
select.js
var dbConnect = require('../oracledb/dbconnect');
dbConnect('select code from table1' +
' where id=:id', {id:'value1'}).then(function (response) {
console.info(response.rows);
}).catch(function(error) {
console.info(error);
});
everything above works great, if I run select.js. How could I bring the response into the botpress chat window? I tried placing the select.js code in index.js event.reply, it doesn't work.
Thanks,
Babu.
I have resolved this by using the promise directly in the action.
return dbConnect('<SQL here>=:id', { id: Id })
.then(function(response) {
var res = response.rows
console.info(res);
const newState = { ...state, status: res}
return newState
})
.catch(function(error) {
console.info(error)
})
Note that response has the resultset.

how to run code sequentially in node js

Hi I have this code but when finish the result is not the espected because didn't run in the sequence that I wish
here is the code:
var user_data = {};
models.games.find({$or: [{w_id: req.user._id}, {b_id: req.user._id}, {owner: req.user._id}]}, function (err, games) {
var req_games = [];
if (!err) {
for (var i in games) {
req_games.push(games[i]);
models.users.findOne({_id: games[i].w_id}, function (err, user) {
req_games[i].w_id = user.user;
console.log(req_games[i].w_id) //< -- 3
});
console.log('a ' + req_games[i].w_id) //<-- 2
}
user_data.games = req_games; // <-- 1
}
});
at the end of the task req_games didnt have any update because it's running in the sequence that I put in the comments in the code
This may help you using Q(promises)
obj.find = function(model, condition) { //make your find to return promise
var deferred = q.defer();
model.find(condition, function(err, results) {
if (err) {
logger.log(err);
deferred.reject(err);
} else {
deferred.resolve(results);
}
});
return deferred.promise;
}
ArraysOfId.forEach(function (id) {
var tempProm = mongoUtilsMethodObj.find(schemaObj.Asset, id).then(function (assetObj) {
---- your code
return q.resolve();
});
promArr.push(tempProm);//push all promise to array
});
q.all(promArr).then(function () {
// this will be called when all promise in array will we resolved
})
Here is a version using the async library to map your game values.
var async = require('async');
var user_data = {};
models.games.find({$or: [{w_id: req.user._id}, {b_id: req.user._id}, {owner: req.user._id}]}, function (err, games) {
if(err) {
// or whatever your error response happens to be
return res.render('user.swig', {error: err});
}
async.map(games, function(game, nextGame) {
models.users.findOne({_id: game.w_id}, function (err, user) {
game.w_id = user.user;
nextGame(err, game);
});
}, function(err, req_games) {
user_data.games = req_games;
res.render('user.swig', {user: user_data});
});
});

Resources