Node Api MongoDB updating date as string - node.js

I have a Node API communicating with MongoDB install. The MongoDB node api ("mongodb": "^3.5.9") insists on converting date objects into String before updating to the db. Can anybody please help?
app.post("/api/updateDocument",auth,(req,res) => {
const collection = req.body.Collection;
incomingmap = req.body.inComingMap
const searchval = req.body.searchVal;
const searchvar = req.body.searchVar;
let findargs = {}
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://...";
MongoClient.connect(url, { useNewUrlParser: true, useUnifiedTopology: true },function(err,db) {
if (err) throw err;
var dbo = db.db();
var coll = dbo.collection(collection);
coll.find({}).toArray(function(err,data) {
data.forEach((item) => {
if (item[searchvar] == searchval) {
for (let key in incomingmap) {
value=incomingmap[key]
console.log(key + " : " + value);
try {
da=Date.parse(value);
//incomingmap[key]=da.toIs;
coll.updateOne({_id:item._id},{$set: {key:da}},function() {})
} catch{
//coll.updateOne({_id:item._id},{$set: {key: value}},function() {})
}
}
return res.json({message:searchval+' updated.'})
} else {
setTimeout(() => {
res.end(`${searchval} could not be found.`)
}, 1000)
}
})
})
})
})
Expected Result
"calibration" : ISODate("2021-11-07T11:23:01.306Z"),
Actual Result
"calibration" : "2021-11-07T01:00:00.000Z",

I wrote a new function to parse the dates and store them back into the inComingMap
for (let key in incomingmap) {
value=incomingmap[key]
console.log(key + ": " + value);
try
{
da=new Date(value);
incomingmap[key]=da;
console.log(key + " = " + value +" is a date "+da);
map[key]=da
}
catch {
map[key]=value
console.log("K"+key + " V" + value );
}
}

Related

Communication between NodeJS and webpage

I built simple weather webpage basing on the tutorial. and I have a webpage with below JS code;
I have also Node JS code( on the bottom) for temperature and pressure sensor written with Johnny-Five. This works perfectly but what I wanna do is display readouts from the sensors setup with NodeJS on the webpage. What is the best approach to do that? I tried to setup this with websocket but it was not really working.
let weather = {
apiKey: "xxxxxxxxxxxxxx",
fetchWeather: function (city) {
fetch(
"https://api.openweathermap.org/data/2.5/weather?q=" + city + "&units=metric&appid=" + this.apiKey
).then((response) => {
return response.json();
})
.then((data) => this.displayWeather(data));
},
displayWeather: function (data) {
const { name } = data;
const { icon, description } = data.weather[0];
const { temp, humidity, pressure } = data.main;
const { speed } = data.wind;
const temperatura = Math.round(temp);
document.querySelector(".miasto").innerText = "Pogoda w " + name;
document.querySelector(".icon").src =
"https://openweathermap.org/img/wn/" + icon + ".png";
document.querySelector(".opis").innerText = description;
document.querySelector(".temperatura").innerText = temperatura + "°C";
document.querySelector(".wilgotnosc").innerText =
"Wilgotność: " + humidity + "%";
document.querySelector(".cisnienie").innerText =
"Ciśnienie: " + pressure + "HPa";
document.querySelector(".wiatr").innerText =
"Prędkość wiatru: " + speed + " km/h";
document.querySelector(".pogoda").classList.remove("loading");
document.body.style.backgroundImage =
"url('https://source.unsplash.com/1600x900/?" + name + "')";
},
search: function () {
this.fetchWeather(document.querySelector(".search-bar").value);
},
};
document.querySelector(".search button").addEventListener("click", function () {
weather.search();
});
document
.querySelector(".search-bar")
.addEventListener("keyup", function (event) {
if (event.key == "Enter") {
weather.search();
}
});
weather.fetchWeather("Katowice");
var five = require("johnny-five");
var board = new five.Board(
{
port: "COM4"
}
);
board.on("ready", function() {
var multi = new five.Multi({
controller: "BMP180",
freq: 500
});
multi.on("change", function() {
console.log("Termometr");
console.log(" Temperatura : ", this.thermometer.celsius, " ℃");
console.log("--------------------------------------");
var pressure2 = Math.round(this.barometer.pressure*100, 1)/10;
console.log("Barometr");
console.log(" Ciśnienie : ", pressure2, " HPa" );
console.log("--------------------------------------");
});
});
I managed to solve the issue. Quite simple but mybe it will help someone here
Data which I am sending are
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8085 })
var obj = {
press: "69",
temp: "24"
}
wss.on("connection", ws => {
ws.send(JSON.stringify(obj));
} );
And I get it:
const ws = new WebSocket("ws://localhost:8085");
ws.addEventListener("open", () => {
console.log("We are connected");
ws.addEventListener("message", (data) => {
console.log(JSON.parse(data.data));
});
});

Code runs before request is completed on NodeJS

I have the following code: (the code runs without issues)
function getValoresAcao(acoes) {
acoes.forEach(acao => {
getValorAcao(acao)
});
console.log("the end")
}
function getValorAcao(acao) {
url = 'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&parse_mode=HTML&symbol='+acao+'&apikey='+API_KEY
request(url, { json: true }, (err, res, body) => {
if (err) { return console.log(err); }
let contador = 0;
let valorDeDoisDias = [];
const dailyJsonObject = body["Time Series (Daily)"]
var objectKeysArray = Object.keys(dailyJsonObject)
objectKeysArray.forEach(function(objKey) {
var objValue = dailyJsonObject[objKey]
if (contador < NUMERO_DE_ELEMENTOS )
{
//console.log(dailyJsonObject);
const valorFechamento = objValue["4. close"]
console.log(valorFechamento);
contador = contador + 1
valorDeDoisDias.push(valorFechamento);
}
});
const textoDiferenca = getDiferencaEmPorcentagem(valorDeDoisDias);
let bigString = "" + acao + " | " + valorDeDoisDias[0] + " | " + textoDiferenca
request(urlTelegram + bigString, { json: true }, (err, res, bodyTelegram) => {
console.log(bodyTelegram);
})
});
}
function getDiferencaEmPorcentagem(valprDeDoisDias) {
let myString = ""
const valorDiaAnterior = valprDeDoisDias[0]
const valorDiaMaisRecente = valprDeDoisDias[1]
myString = (valorDiaAnterior - valorDiaMaisRecente ) / valorDiaMaisRecente * 100
myString = myString.toFixed(2)
console.log(myString)
return myString + "%"
}
But the code console.log("the end") is supposed to run after the request is completed, but it runs when I start the code, it didn't wait the request to be finished.
How can I make the "the end" part of the code wait the request be executed?
probably something like that could help:
async function getValoresAcao(acoes) {
await Promise.all(acoes.map(getValorAcao))
console.log("the end")
}
async function getValorAcao(acao) {
const url = 'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&parse_mode=HTML&symbol=' + acao + '&apikey=' + API_KEY
return new Promise ((resolve, reject)=>{
try{
request(url, { json: true }, (err, res, body) => {
if (err) {
throw err
}
let contador = 0;
let valorDeDoisDias = [];
const dailyJsonObject = body["Time Series (Daily)"]
var objectKeysArray = Object.keys(dailyJsonObject)
objectKeysArray.forEach(function (objKey) {
var objValue = dailyJsonObject[objKey]
if (contador < NUMERO_DE_ELEMENTOS) {
//console.log(dailyJsonObject);
const valorFechamento = objValue["4. close"]
console.log(valorFechamento);
contador = contador + 1
valorDeDoisDias.push(valorFechamento);
}
});
const textoDiferenca = getDiferencaEmPorcentagem(valorDeDoisDias);
let bigString = "" + acao + " | " + valorDeDoisDias[0] + " | " + textoDiferenca
request(urlTelegram + bigString, { json: true }, (err, res, bodyTelegram) => {
if(err){
throw err
}
resolve(bodyTelegram)
})
});
} catch (e) {
reject(e)
}
})
}
function getDiferencaEmPorcentagem(valprDeDoisDias) {
let myString = ""
const valorDiaAnterior = valprDeDoisDias[0]
const valorDiaMaisRecente = valprDeDoisDias[1]
myString = (valorDiaAnterior - valorDiaMaisRecente) / valorDiaMaisRecente * 100
myString = myString.toFixed(2)
console.log(myString)
return myString + "%"
}

Node.js with Mongoose database find issue

I have been having an very odd issue and I think it might be the way I am doing nested levels in the mongoose schema. First lets get the schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var RLSchema = new Schema({
user_id: { type: String, required: true },
coordinate: {
accuracy: Number,
latitude: Number,
longitude: Number
},
agency_id: String,
received_time: { type: Date, default: Date.now },
department_id: String
});
module.exports = mongoose.model('RL', RLSchema);
And I am creating a dynamic search with this since I dont know what they are going to search with. All I know is if you are searching based on received_time you need to send in the To and From:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var regexp = require('node-regexp');
var RL = require('./app/models/rl');
var uristring = process.env.MONGODB_URI || 'mongodb://localhost/mydev';
mongoose.connect(uristring, function (error) {
if (error) {
console.log(error);
}
});
app.get('/api/rl', function(req, res) {
var findQuery = "{";
var qry = "";
if (req.query.agency_id) {
findQuery = findQuery + " agency_id: \"" + req.query.agency_id + "\",";
}
if (req.query.department_id) {
findQuery = findQuery + " \"department_id\": \"" + req.query.department_id + "\",";
}
if (req.query.user_id) {
findQuery = findQuery + " \"user_id\": \"" + req.query.user_id + "\",";
}
var isOne = ((req.query.from) || (req.query.to));
var isBoth = ((req.query.from) && (req.query.to));
if (isOne) {
if (isBoth) {
findQuery = findQuery + " \"received_time\": { \"$lte\": " + req.query.to + ", \"$gte\": " + req.query.from + "},"
} else {
res.status(400).json("{ message: 'Missing the to or from time for searching}'");
return res;
}
}
qry = findQuery.substring(0, findQuery.length - 1);
qry = qry + "}";
if (qry.length < 2) {
qry = "{}";
}
if (!isBoth) {
qry = "";
}
RL.find(JSON.parse(qry)).toArray(function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to get information");
} else {
res.status(200).json(doc);
}
});
});
Everytime I call this I get back:
Error
Internal Server Error
even if I remove all the code and just send in what is below I still get the Internal Server Error. Do you know why this would not work?
ResponderLocation.Find({ agency_id: req.query.agency_id }).toArray(function(err, rl){
if(err)
res.send(err);
res.json(rl);
});
As q4w56 pointed out, you should build an object opposed to a string and there is no function Find.
Here's how I would refactor your code:
app.get('/api/rl', function(req, res) {
var query = {};
if (req.query.agency_id) {
query.agency_id = req.query.agency_id;
}
if (req.query.department_id) {
query.department_id = req.query.department_id;
}
if (req.query.user_id) {
query.user_id = req.query.user_id;
}
if (!req.query.from && !req.query.to) {
// .json() expects a JSON not a string as argument
return res.status(400).json({ message: 'Missing the to or from time for searching' });
}
query.received_time = {};
if (req.query.from) {
query.received_time.$gte = req.query.from;
}
if (req.query.to) {
query.received_time.$lte = req.query.to;
}
// no need for toArray()
ResponderLocation.find(query, function(err, locations) {
if (err) {
handleError(res, err.message, "Failed to get information");
} else {
// no need to send 200 status as that is default
res.json(locations);
}
});
});

Make my db queries synchronous with with my promise based function

How can I make my db queries synchronous with with my promise base function? In my code, I am running 3 db operations inside 3 different functions which need to be run in order, like waterfall model. The functions are running in waterfall model but db queries inside those functions are working in asynchronous. I need to run db queries inside those function in synchronous.
In this example I am expecting in console:
1
2
3
4
But I am getting
1
3
2
4
Code:
const Promise = require('bluebird');
// DB Settings
const dbConfig = {
user: process.env.DBUSER,
password: process.env.DBPWD,
database: process.env.DBNAME,
host: process.env.DBHOST,
port: process.env.DBPORT,
poolSize: 10, // max number of clients in the pool
//poolIdleTimeout: 30000, // how long a client is allowed to remain idle before being closed
//reapIntervalMillis: 1000 //frequency to check for idle clients within the client pool
};
const pgp = require('pg-promise')();
const db = pgp(dbConfig);
var currentStatus = '',newStatus = '';
const _updateCurrentStatus = () => new Promise((resolve, reject) => {
const _getCurrentStatus = (_userId) => new Promise((_resolve, _reject) => {
console.log("1");
let statusQuery = "SELECT status FROM users WHERE id=" + _userId;
db.one(statusQuery).then(function (data) {
console.log("2");
currentStatus = data.status;
_resolve();
}).catch(function (error) {
_reject(error);
});
});
const _setUpdateStatus = (cStatus, nStatus) => new Promise((_resolve, _reject) => {
if(allApproved){
if(cStatus == 'nvd_pending'){
//nStatus = 'finance_pending';
newStatus = 'finance_pending';
}else if(cStatus == 'finance_pending'){
//nStatus = 'oracle_pending';
newStatus = 'oracle_pending';
}else if(cStatus == 'oracle_pending'){
//nStatus = 'active';
newStatus = 'active';
}else{
//nStatus = cStatus;
newStatus = cStatus;
}
}else{
//nStatus = 'nvd_pending';
newStatus = 'nvd_pending';
}
//_resolve(nStatus);
_resolve();
});
const _updateStatus = (_newStatus, _payLoad) => new Promise((_resolve, _reject) => {
console.log("3");
let updateuserQuery = "UPDATE users SET status = '"+ _newStatus + "' WHERE id=" + _payLoad.user_id;
let updatePanQuery = "UPDATE user_documents SET status = '" + _payLoad.panstatus + "' WHERE id= " + _payLoad.panid + " AND user_id=" + _payLoad.user_id;
let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + _payLoad.financestatus +" 'WHERE id= " + _payLoad.financeid + " AND user_id=" + _payLoad.user_id;
db.tx(function (t) {
console.log("4");
// `t` and `this` here are the same;
// this.ctx = transaction config + state context;
return t.batch([
t.none(updateuserQuery),
t.none(updatePanQuery),
t.none(updateFinanceQuery)
]);
}).then(function (data) {
_resolve(data);
}).catch(function (error) {
_reject(error);
});
});
_getCurrentStatus(payLoad.user_id)
.then(_setUpdateStatus)
.then( _updateStatus(newStatus, payLoad))
.then( values => {
resolve(values);
},error => {
reject(error);
})
.catch((error) => reject(error));
});
You are overcomplicating thing here. First feedback is that you don't need those new Promise wrappers, since pg-promise is already creating promises. You can greatly flatten things here:
function getCurrentStatus(userId) {
console.log("1");
let statusQuery = "SELECT status FROM users WHERE id=" + userId;
return db.one(statusQuery).then(function (data) {
console.log("2");
return data.status;
});
}
function getUpdatedStatus(cStatus)
console.log('2');
if (allApproved) {
if(cStatus == 'nvd_pending'){
newStatus = 'finance_pending';
} else if (cStatus == 'finance_pending'){
newStatus = 'oracle_pending';
} else if (cStatus == 'oracle_pending'){
newStatus = 'active';
} else {
newStatus = cStatus;
}
} else {
newStatus = 'nvd_pending';
}
return newStatus;
}
function updateStatus(newStatus, payLoad) {
console.log("3");
let updateuserQuery = "UPDATE users SET status = '"+ newStatus + "' WHERE id=" + payLoad.user_id;
let updatePanQuery = "UPDATE user_documents SET status = '" + payLoad.panstatus + "' WHERE id= " + payLoad.panid + " AND user_id=" + payLoad.user_id;
let updateFinanceQuery = "UPDATE user_finance_details SET status = '" + payLoad.financestatus +" 'WHERE id= " + payLoad.financeid + " AND user_id=" + payLoad.user_id;
return db.tx(function (t) {
console.log("4");
// `t` and `this` here are the same;
// this.ctx = transaction config + state context;
return t.batch([
t.none(updateuserQuery),
t.none(updatePanQuery),
t.none(updateFinanceQuery)
]);
});
});
function updateCurrentStatus(payLoad) {
return getCurrentStatus(payLoad.user_id)
.then(cStatus => getUpdatedStatus(cStatus))
.then(newStatus => updateStatus(newStatus, payLoad));
}
The specific reason you're seeing 3 out of order is because you're calling it immediately via _updateStatus(newStatus, payLoad) instead of wrapping it in a function (see my suggested code updates above).

TypeError: Cannot read property 'emails' of null

Here is line 54, where I am getting the error:
if (docr.emails) {
And here is the rest of my original code:
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var config = require('./config'),
xlsx = require('./xlsx'),
utils = require('./utils'),
_ = require('lodash'),
url = config.DB_URL;
var meetings = [];
function findNumberOfNotesByMeeting(db, meeting, callback) {
var meetingId = meeting._id.toString(),
meetingName = meeting.name.displayValue,
attendees = meeting.attendees;
host = meeting.host;
var count = 1, pending = 0, accepted = 0;
console.log("==== Meeting: " + meetingName + '====');
_.each(attendees, function(item) {
console.log(count++ + ': ' + item.email + ' (' + item.invitationStatus + ')');
if (item.invitationStatus == 'pending') { pending++; }
else if (item.invitationStatus == 'accepted') { accepted++; }
});
console.log("*** " + attendees.length + ", " + pending + "," + accepted);
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, doc) {
var emails = [];
if (doc.emails) {
doc.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
db.collection('notes').find({ 'meetingId': meetingId }).count(function(err, count) {
if (count != 0) {
console.log(meetingName + ': ' + count + ',' + attendees.length + ' (' + email + ')');
meetings.push([ meetingName, count, email, attendees.length, pending, accepted ]);
}
callback();
});
}
});
}
function findMeetings(db, meeting, callback) {
var host = meeting.host;
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, docr) {
var emails = [];
if (docr.emails) {
docr.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
var email = emails.join(', ');
if (utils.toSkipEmail(email)) {
callback();
} else {
var cursor = db.collection('meetings').find({
'email': {'$regex': 'abc', '$options': 'i' }
});
}
cursor.count(function(err, count) {
console.log('count: ' + count);
var cnt = 0;
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
findNumberOfNotesByMeeting(db, doc, function() {
cnt++;
if (cnt >= count) { callback(); }
});
}
});
});
});
};
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findMeetings(db, function() {
var newMeetings = meetings.sort(function(m1, m2) { return m2[1] - m1[1]; });
newMeetings.splice(0, 0, [ 'Meeting Name', 'Number of Notes', 'Emails' ]);
xlsx.writeXLSX(newMeetings, config.xlsxFileNameMeetings);
db.close();
});
});
Try the following:
function findMeetings(db, meeting, callback) {
var host = meeting.host;
db.collection('users').findOne({'_id': new ObjectId(host)}, function(err, docr) {
var emails = [];
if (!err && docr && docr.emails) {
docr.emails.forEach(function(e) {
emails.push(e.email + (e.primary ? '(P)' : ''));
});
}
...

Resources