Hello im trying to query my mongoDB collection to find all data from specific date.
For some reason when I use Find() with the object specified as param in the call it works
but when I try to declare a variable it doesnt .... can some explain me why?
this doesnt work
//Convert Date to short Date string
let day = foundRapport.date.getUTCDate();
let fullMonth = foundRapport.date.getMonth() + 1;
let year = foundRapport.date.getFullYear();
let date = `${day}/${fullMonth}/${year}`;
//query for Date_Travail
let query = {};
let criteria = "Date_Travail";
query[criteria] = date;
console.log(query); // this returns { Date_Travail: '24/7/2020' }
//Find data with query as param
Heures.find(query, (err, foundHours) => {
if (err) {
console.log(err);
} else {
res.render("rapportDetail", {
rapport: foundRapport,
shortDate: date,
hours: foundHours,
});
}
});
But this here does....
//Convert Date to short Date string
let day = foundRapport.date.getUTCDate();
let fullMonth = foundRapport.date.getMonth() + 1;
let year = foundRapport.date.getFullYear();
let date = `${day}/${fullMonth}/${year}`;
// let query = {};
// let criteria = "Date_Travail";
// query[criteria] = date;
// console.log(query);
//Find data with object as param
Heures.find({Date_Travail: "24/07/2020"}, (err, foundHours) => {
if (err) {
console.log(err);
} else {
res.render("rapportDetail", {
rapport: foundRapport,
shortDate: date,
hours: foundHours,
});
}
});
can anyone point me on the direction of why?
Thanks
Related
I´m quite new with Node.js and MongoDB and I`m having trouble when build queries.
For example I want to filter the date of my object depending on the request. This is what I did:
var startDate = req.body.startDate;
var endDate = req.body.endDate;
let findParams = {
userId:req.userId
};
if(startDate){
findParams["start"] = { $gt: new Date(startDate)};
}
if(endDate){
findParams["start"] = { $lt: new Date(endDate)};
}
if(startDate && endDate){
findParams["start"] = { $gt: new Date(startDate),$lt: new Date(endDate)};
}
console.log(findParams);
WorkTime.find(findParams)
I have to build the "start" param every time depending on what the user sends. If the user sends both values (startDate & endDate) I have to build the params object again.
What would be the optimal way to build this query?
Thanks in advance!
You code is fine. There is no any "optimal" way, but a bit "elegant"
try {
var startDate = req.body.startDate;
var endDate = req.body.endDate;
let findParams = {
userId: req.userId
};
if (startDate || endDate) {
findParams["start"] = { };
if (startDate) {
findParams["start"]["$gt"] = new Date(startDate);
}
if (endDate) {
findParams["start"]["$lt"] = new Date(endDate);
}
}
console.log(findParams);
WorkTime.find(findParams)
} (catch e) {
console.log("Error occured: " + e);
}
I have this intent that has a cheerio.load() being called and it messes with with the responses. The Google Assistant keeps telling me that no response has been set even though later down in the code I have responses. The console is also telling me that an async call wasn't being returned to the handler, which I believe is the cheerio.load(). Is there anyway I can fix this so that it continues looking for the correct conv.ask at the bottom of the code? It still continues to run down to there too, for the console.log(map) shows up. Thanks for any help!
app.intent("late drop", (conv,{term,year}) => {
var date = new Date();
var month;
if(term == null){
month = date.getMonth();
if(month >= 9 && month <=12){
term = "fall";
//console.log("fall")
}
else if (month >= 1 && month <= 5) {
term = "spring";
//console.log("spring")
}
else {
term = "summer";
//console.log("summer")
}
}
if(year == null){
yearDig = date.getFullYear();
year = yearDig;
//console.log(year)
}
var strYear = year.toString();
var semester = term+strYear.substr(2);
const options = {
uri: `https://www.registrar.psu.edu/academic_calendar/${semester}.cfm`,
transform: function (body) {
return cheerio.load(body);
}
};
rp(options)
.then(($) => {
let map = {};
let columnOne = [];
let columnThree = [];
$('table').find('tr td:nth-child(1)').each(function (index, element) {
columnOne.push($(element).text());
});
$('table').find('tr td:nth-child(3)').each(function (index, element) {
columnThree.push($(element).text());
});
columnOne.forEach((item, i) => {
map[item] = columnThree[i];
});
console.log(map);
date = map["2Late Drop Begins"];
conv.ask("The late drop period begins on " + map["2Late Drop Begins"])
})
.catch((error) => {
console.log(error);
conv.ask("An error occured, please try again.");
})
});
The issue is not with cheerio.
It looks like you are using request-promise or request-promise-native to make your HTTP call. This does an asynchronous operation that will return a Promise (as is evidenced by your use of .then() and .catch().
Since Intent Handlers that do asynchronous operations must return a Promise, you can simply return the one that is returned by the rp/then/catch chain. Something like changing this line should work:
return rp(options)
I have modified your code to return a Promise. Check if this works for you.
app.intent("late drop", (conv, {
term,
year
}) => {
return new Promise(function (resolve, reject) {
var date = new Date();
var month;
if (term == null) {
month = date.getMonth();
if (month >= 9 && month <= 12) {
term = "fall";
//console.log("fall")
} else if (month >= 1 && month <= 5) {
term = "spring";
//console.log("spring")
} else {
term = "summer";
//console.log("summer")
}
}
if (year == null) {
yearDig = date.getFullYear();
year = yearDig;
//console.log(year)
}
var strYear = year.toString();
var semester = term + strYear.substr(2);
const options = {
uri: `https://www.registrar.psu.edu/academic_calendar/${semester}.cfm`,
transform: function (body) {
return cheerio.load(body);
}
};
rp(options)
.then(($) => {
let map = {};
let columnOne = [];
let columnThree = [];
$('table').find('tr td:nth-child(1)').each(function (index, element) {
columnOne.push($(element).text());
});
$('table').find('tr td:nth-child(3)').each(function (index, element) {
columnThree.push($(element).text());
});
columnOne.forEach((item, i) => {
map[item] = columnThree[i];
});
console.log(map);
date = map["2Late Drop Begins"];
conv.ask("The late drop period begins on " + map["2Late Drop Begins"])
resolve()
})
.catch((error) => {
console.log(error);
conv.ask("An error occured, please try again.");
reject()
})
});
});
Hope that helps!
hello all I am new to node js and mongo db so I am facing a problem which is written above want to match an id from an array and get all the record of matching id , but thats not working i have already tried for loop but that is taking too much time so i am looking for some kind of query by which I pass id and get the matching results i have below function also where i can pass id and get the matching result but i don't know how to call that .
exports.getDistrictFromId = function(req, res, next) {
var distId = req.params.id;
districtslib.getDistricts({_id: utils.toObjectId(distId)}, function(err, district) {
if (err) {
return next(err);
}
req.store.district = district;
next();
});
};
Here is my code
exports.getCompleteTeachersList = function(req, res, next) {
var query = req.store.get('query');
var teacherQuery = {enabled: true};
var searchQuery = '';
if (!_.isUndefined(query)) {
// schoolQuery = {'name':new RegExp(query.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"),'i')};
//{ $text: { $search: "amit hinduja"} }
//teacherQuery = {enabled: true,$or:[{firstName:new RegExp(query.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"),'i')},{lastName:new RegExp(query.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"),'i')}]};
if(query.trim() != '') {
teacherQuery = {enabled: true,$text: { $search: query} };
searchQuery = query;
}
}
teacherslib.getTeachers(teacherQuery, function(err, teachers) {
if (err) {
return next(err);
}
var schools = req.store.get('schools');
for(var i = 0; i < teachers.length; i++) {
teachers[i].schoolName = "";
for(var j = 0; j < schools.length; j++) {
if (teachers[i].schoolId.toString() === schools[j]._id.toString()) {
teachers[i].schoolName = schools[j].name;
teachers[i].distId = "";
var districts = req.store.get('districts');
console.log(schools[j].distId);
// i want to get the array of matching district id `schools[j].distId` from the district array from `var districts = req.store.get('districts');` this line
break;
}
}
}
req.store.set('searchQuery', searchQuery);
req.store.set('teachers', teachers);
//req.store.set('districts', districts);
next();
});
};
Collection structure is like this
1) distid is coming in schools collection
using distid get all the matching record from district
2)district array has countyid and from that county id has to get data from the county collection
Instead of looping inside a loop, i would suggest you look into the $lookup operator of the aggregation framework. Here you can perform the lookup server side.
It is 2016, Node has had nearly full ES6 support since v4, and Promises have been around since 0.12. It's time to leave callbacks in the dust IMO.
I'm working on a commander.js-based CLI util which leverages a lot of async operations - http requests and user input. I want to wrap the Commander actions in async functions so that they can be treated as promises, and also to support generators (useful for the co-prompt library I'm using for user input).
I've tried wrapping the CB with co in two ways:
1)
program.command('myCmd')
.action(program => co(function* (program) {...})
.catch(err => console.log(err.stack)) );
and
2) program.command('myCmd').action(co.wrap(function* (program) { .. }));
The problem with 1) is that the program parameter isn't passed
The problem with 2) is that errors are swallowed...
I'd really like to get this working as it yields much nicer code in my use case - involving a lot of http requests and also waiting for user input using the co-prompt library..
Is it a better option altogether perhaps to wrap program.Command.prototype.action somehow?
thanks!
I've used a bespoke version of something like co to get a db.exec function which uses yield to do database request. You can pass parameters into a generator function (I pass in a connection object - see the comment where I do it).
Here is by db.exec function that is very similar to what co does
exec(generator) {
var self = this;
var it;
debug('In db.exec iterator');
return new Promise((accept,reject) => {
debug('In db.exec Promise');
var myConnection;
var onResult = lastPromiseResult => {
debug('In db.exec onResult');
var obj = it.next(lastPromiseResult);
if (!obj.done) {
debug('db.exec Iterator NOT done yet');
obj.value.then(onResult,reject);
} else {
if (myConnection) {
myConnection.release();
debug('db.exec released connection');
}
accept(obj.value);
debug('db.exec Promise Resolved with value %d',obj.value);
}
};
self._connection().then(connection => {
debug('db.exec got a connection');
myConnection = connection;
it = generator(connection); //This passes it into the generator
onResult(); //starts the generator
}).catch(error => {
logger('database', 'Exec Function Error: ' + error.message);
reject(error);
});
});
}
the connection object also wraps by database connection object and provides a generator function ability to process the rows of the results from the database, but I won't post that here (although the example below is using it to process the rows).
Here is an example of using the exec function to run a sequence of sql
db.exec(function*(connection) {
if (params.name === ADMIN_USER) {
debug('Admin Logon');
user.name = ADMIN_DISPLAY;
user.keys = 'A';
user.uid = 0;
let sql = 'SELECT passwordsalt FROM Admin WHERE AdminID = 0';
connection.request(sql);
yield connection.execSql(function*() {
let row = yield;
if (row) {
user.nopass = (row[0].value === null);
} else {
user.nopass = false;
}
debug('Admin Password bypass ' + user.nopass.toString());
});
} else {
debug('Normal User Logon');
let sql = `SELECT u.UserID,PasswordSalt,DisplayName,AccessKey,l.LogID FROM Users u
LEFT JOIN UserLog l ON u.userID = l.userID AND DATEDIFF(D,l.LogDate,GETDATE()) = 0
WHERE u.UserName = #username`;
let request = connection.request(sql);
request.addParameter('username',db.TYPES.NVarChar,params.name);
let count = yield connection.execSql(function*() {
let row = yield;
if (row) {
user.uid = row[0].value;
user.name = row[2].value;
user.keys = (row[3].value === null) ? '' : row[3].value;
user.nopass = (row[1].value === null) ;
user.lid = (row[4].value === null) ? 0 : row[4].value;
debug('Found User with uid = %d and lid = %d, keys = %s',
user.uid, user.lid, user.keys);
}
});
if (count === 0) {
debug('Not Found User');
// couldn't find name in database
reply(false,false);
return;
}
}
if (!user.nopass) {
debug('Need a Password');
//user has a password so we must check it
passGood = false; //assume false as we go into this
let request = connection.request('CheckPassword');
request.addParameter('UserID',db.TYPES.Int,user.uid);
request.addParameter('password',db.TYPES.VarChar,params.password);
yield connection.callProcedure(function*() {
let row = yield;
if (row) {
//got a valid row means we have a valid password
passGood = true;
}
});
} else {
passGood = true;
}
if (!passGood) {
debug('Not a Good Pasword');
reply(false,true);
} else {
if (user.uid !== 0 && user.lid === 0) {
let sql = `INSERT INTO UserLog(UserID,LogDate,TimeOn,UserName) OUTPUT INSERTED.logID
VALUES(#uid,GETDATE(),GETDATE(),#username)`;
let request = connection.request(sql);
request.addParameter('uid',db.TYPES.Int,user.uid);
request.addParameter('username',db.TYPES.NVarChar,user.name);
yield connection.execSql(function*() {
let row = yield;
if (row) {
user.lid = row[0].value;
debug('Users Log Entry = %d',user.lid);
}
});
}
reply(true,user);
}
})
.catch((err) => {
logger('database','Error on logon: ' + err.message);
reply(false,false);
});
});
There is a quite simple way to do async function in Commander.js
async function run() {
/* code goes here */
}
program
.command('gettime')
.action(run);
program.parse(process.argv);
I try to use limit : count with transform observer in Meteor and don't understand how to do it without "dirty" solutions.
Code I have on Client (not all, but main part)
var self = this;
self.autorun(function() {
self.subscribe('posts', Session.get('count')); // some Number like 10
}); // client
And on server where I try to use it
Meteor.publish('posts', function(count){
check(count, Number);
let i = 0;
var transform = function(doc) {
console.log(i,count);
if (i < count){ // I try something here
doc.description = new Date();
i++;
return doc;
}
else self.ready();
}
var self = this;
var observer = Posts.find().observe({
added: function (document) {
self.added('posts', document._id, transform(document));
},
changed: function (newDocument, oldDocument) {
self.changed('posts', document._id, transform(newDocument));
},
removed: function (oldDocument) {
self.removed('posts', oldDocument._id);
}
});
self.onStop(function () {
observer.stop();
});
self.ready();
});
Any idea how to limit count of shown documents with transform in publish ?
Just use Posts.find({},{limit:count}) in your query.