How do you display the results of a mongodb aggregation query using node.js, express & jade
I'm not sure what I've done wrong or even if this is the correct approach.
When I attempt to access the page - it just times out?
Any idea? Or is there a better way?
app.js
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/soundevents');
var timeroute = require('./routes/timers');
app.get('/time/starttimer', timeroute.starttimer);
my routes/timers.js looks like this:
exports.starttimer = function(db) {
return function(req, res) {
var aEvent = db.get('event');
aEvent.aggregation([{$group:{_id:{"EventName":"$EventName"}}}],{}, function(e,docs) {
res.render('time/starttimer', {title: 'Stat Timer',
"eventlist" : docs});
});
};
};
output from mongo
db.event.aggregate([{$group:{_id:{"EventName":"$EventName"}, UpdateTime:{$max: "$UpdateTime"}}}])
{"result" : [{"_id" : {
"EventName" : "MtnBikeRace 1"},
"UpdateTime" : 1392265180.069293},
{"_id" : {
"EventName" : "Student League"},
"UpdateTime" : 1392047321724}],
"ok" : 1}
This example can help you.
https://github.com/visionmedia/express/blob/master/examples/jade/index.js
// Dummy users
var users = [
new User('tj', 'tj#vision-media.ca')
, new User('ciaran', 'ciaranj#gmail.com')
, new User('aaron', 'aaron.heckmann+github#gmail.com')
];
app.get('/', function(req, res){
res.render('users', { users: users });
})
// user.jade
extends ../layout
block content
h1 Users
#users
for user in users
.user
h2= user.name
.email= user.email
I landed here because I was looking for a way to aggregate results using monk.
For future reference: as of now, monk has no .aggregate() method, therefore this part of your code will not work (as you've indicated in a comment):
// there's no aggregation method.
aEvent.aggregation([{$group:{_id:{"EventName":"$EventName"}}}],{}, function(e,docs) {
res.render('time/starttimer', {title: 'Stat Timer',
"eventlist" : docs});
});
However,
this answer shows the correct way to perform an aggregation with monk. It uses the underlying native driver. In your case this would be something like the following:
aEvent.col.aggregate([{$group:{_id:{"EventName":"$EventName"}}}],{}, function(e,docs) {
res.render('time/starttimer', {title: 'Stat Timer',
"eventlist" : docs});
});
If you aggregate this way, I guess you can accept fundon's answer.
Related
What I am trying to do: I am fetching data from MongoDB(doc). I has property files which is an array of objects. Schema of the mentioned object:
{
fileName : {type : String, required : true},
fileSize : {type : Number, required : true},
fileOriginalName : String,
sentEarlier : Boolean,
}
and before sending this array(in doc.files) to my frontend, I want to append a property(downloadLink), to each object. The whole code where I encountered the problem:
Router.post('/fetch-more-files', (req, res) => {
let {uuid} = req.body;
File.findOne({uuid}, (err, doc) => {
if(err) {
return res.send({'error' : 'Something went wrong. Refresh the page.'});
}
if(!doc) {
return res.send({'error' : 'Invalid link or link expired'});
}
let newFiles = [];
doc.files.forEach(file => {
file.downloadLink = `${process.env.APP_BASE_URL}/files/download/${uuid}/${file.fileName}`;
});
doc.files.forEach(file => {
if(!file.sentEarlier) newFiles.push(file);
});
doc.save((err, savedDoc) => {
res.json({newFiles});
});
});
});
PROBLEM: The newFiles array which I am populating with all the files(objects inside doc.files array), those that do not have a 'sentEarlier' key true to them, when sent as response, not a single object that array has the 'downloadLink' property to them. I tried so hard and for so long to debug, but failed. Hope to find some insights as to what I could be doing wrong here. Thanks in advance!!!
SOLUTION: After hours of lingering and loitering over this problem, I found a solution. If you want the technical answer to why it didn't work, this is not the place for you. But if you just want your problem solved, so you can finally go pee, read on.
The answer is to use toObject() method which apparently converts the mongoose document to a plain JS object, which is now at your disposal.
toObject() in mongooseJS documentation:
Mongoose v5.11.9:API docs | document.prototype.toObject()
Other answers are most welcome.
Mongoose queries return an instance of the Mongoose Document class. if you want to modify your query response just try to call your mongoose query in a different way.
File.findOne({uuid}, {new: true}).lean().exec((err, doc) => {
if(err) {
return res.send({'error' : 'Something went wrong. Refresh the page.'});
}
// your logic
});
here you get more idea about lean()
I have to try to store my child info into MongoDB via using postman tool. But it shows me this message "message": "child info validation failed"
in postman console. child info is my collection name where I store my child info.
my requirement is to store the result in array form as below schema mentioned inside MongoDB
1). This is js child schema
userId:{
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
quiz:[
{
questionId:{
type: mongoose.Schema.Types.ObjectId,
ref: 'questions'
},
score:{type:String},
time:{type:String}
}
]
2). This is node js
try {
var quizArr = [];
var quizObj = {
'questionId': req.params.questionId,
'score': req.params.score,
'time': new Date().toISOString()
};
quizArr.push(quizObj);
var userObj = {
'userid': req.params.userId,
'quiz': quizArr
};
//var parseObj = Json.stringify(userObj); This line is comment
var childinfoSave = new QuizChildInfo(userObj);
childinfoSave.save(function (err) {
if (err) return next(err);
res.send("Child questionId score and date saved successfully")
console.log("Child questionId score and date saved successfully");
});
}catch(err){console.log(err);}
3). Output of postman screen
{
"message": "childinfos validation failed"
}
4). Output of console
Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
5). Mongo console
{
"_id" : ObjectId("57bc483169e718642ac0ac44"),
"levelsAttempted" : [ ],
"quiz" : [ ],
"__v" : 0
}
For the problem of your console,
put mongoose.Promise = global.Promise; in the file where you have established your server connection( like in my case its index.js).
And i think you may have not posted the whole code as i couldnt find childinfos in your code.
I have a setup with Node, Express, and using backbone. Everything works fine and I'm able to retrieve records from by MongoDB collections when they are simple as in getting employees by id or all employees. What I'm having trouble understanding is how to get collections from MongoDB that require a more complex query syntax like the following:
db.employees.aggregate(
[
{ $group : { _id : "$managerName", employees: { $push: "$fullName" } } }
]
)
I currently have the following syntax for extracting the data I want to expose as a json object and bind to the elements in my html page.
exports.findById = function(req, res) {
var id = parseInt(req.params.id);
db.collection('employees', function(err, collection) {
collection.findOne({'id': id}, function(err, item) {
res.jsonp(item);
});
});
};
I want to get a list of all Managers and they employees that report to them and then somehow bind this result set to individual divs that would list a Manager as the List heading, and then all the employees that report to them as list items. The result set will essentially consist of parents and childs. I want to do this dynamically using backbonejs.
Would I be doing something like
exports.findRelations = function(req, res) {
db.collection('employees', function(err, collection) {
collection.aggregate({ $group : { _id : "$managerName", employees:{$push: "$fullName" } } }, function(err, item) {
res.jsonp(item);
});
});
};
The aggregation pipeline for MongoDB requires that you pass the operations in an Array. This means the correct query would be:
db.collection('employees').aggregate([
{ $group : { _id : "$managerName", employees:{$push: "$fullName" } }
])
.toArray(function(err, managers){
if (err){
throw err;
}
res.jsonp(managers);
});
You'll find details for using the aggregation pipeline with the NodeJS MongoDB driver here: https://docs.mongodb.org/getting-started/node/aggregation/
I want to get a value in my url.
My url is like :
host/:value.schema
I want to get value.
Exemple :
host/horse.schema value = horse
I have another route without .schema:
host/:value
Exemple :
host/horse value = horse
How tell Express to make the difference ?
You can try something like this:
app.get('/:value.:schema?', function (req, res) {
console.log(req.params);
});
You'll receive this:
http://localhost:3000/horse { value: 'horse', schema: undefined }
http://localhost:3000/horse.schema { value: 'horse', schema: 'schema' }
I am trying to retrieve a document from MongoDB. The document has the field "ownerId" that contain a binary UUID. Using the Mongo console if I launch the command
db.dataset.find({ownerId: BinData(3,"ZQ6EAOKbQdSnFkRmVUUAAA==")}).pretty()
it returns:
{
"_id" : BinData(3,"VQ6EAOKbQdSnFkRmVUUAAA=="),
"name" : "Twitter",
"objectType" : "Tweet",
"ownerId" : BinData(3,"ZQ6EAOKbQdSnFkRmVUUAAA==")
}
When I try to retrieve the document from my node.js program, it fails and does not return any document.
My program is:
var mongo = require('mongoskin');
var db = mongo.db("mongodb://192.168.1.100:27017/test", {native_parser:true});
function HexToBase64(g) {
...
}
var uuidstr = "650e8400e29b41d4a716446655450000";
console.info(uuidstr);
base64str = HexToBase64(uuidstr);
console.info(base64str);
db.collection('dataset').find( { ownerId:new mongo.Binary(base64str, 4) } ).toArray(function (err, items) {
if(err) {
var msg = "Error getting 'dataset' objects from database.";
console.info(msg + " " + err);
return;
}
console.info("OK");
console.info(items);
});
The output is:
650e8400e29b41d4a716446655450000
ZQ6EAOKbQdSnFkRmVUUAAA==
OK
[]
What am I doing wrong?
Firstly, since you're going to query the collection by OwnerId, I'd suggest to create an index there. You can achieve that in mongoskin easily enough:
// Create and index by ownerId
db.collection('dataset').ensureIndex([['ownerId', 1]], true, function(err, res) {
if (err) throw err;
});
Once you've done that, you can now do things like this:
db.collection('dataset').findOne({ ownerId: 'some-uuid' }, callback);
Further, if it's the ObjectId type you're after, I'd recommend you use the provided helper (see this other question) to achieve that:
var ownerId = mongoskin.ObjectID(uuidstr);
Otherwise, I'd go with a different approach, perhaps using node-uuid :
var uuid = require('node-uuid');
var ownerId = uuid.v4();
db.collection('dataset').findOne({ ownerId: ownerId }, callback);
Hope this helps,