Node js mongodb group - node.js

Here is my history model. It contains three fields:Content,Year,Month
sample data like:
1 "aaaaa",2012,12
2 "bbbbb",2013,11
3 "ccccc",2012,09
I want to group by "Year" field,and store like this:
[{"aaaaa",2012,12}},{"ccccc",2012,09}],
[{"bbbbb",2013,11}],
Here is my code:
// index.js
var hisArrs = [];
History.distinct("Year", function(err, doc) {
var years = doc;
years.forEach(function(year) {
History.find({"Year": year}, function(err, docs){
hisArrs.push(docs);
});
});
});
res.render('History/history', {
title: 'history',
HisArrs: hisArrs
});
However, I don't understand why. Could you please help on this?

Related

Multi level population in Mongoose is not working

I have three models, programs (Program), tiers(Tier), offers (Offer). A program can have multiple tiers and a tiers can have multiple offers. So my program has an array of tiers and correspondingly a tier can have array of offers. Now I am trying to populate programs as follows:
var Program = mongoose.model('Program');
var Offer = mongoose.model('Offer');
var Tier = mongoose.model('Tier');
Program.findOne({
_id: p_id
}).populate('tiers').exec(function(err, docs){
var opts = {
path: 'tiers.offers'
}
Program.populate(docs, opts, function(err, docs){
console.log('populated');
// var s = require('util').inspect(docs, {depth : null})
console.log(docs);
console.log(docs.tiers[0]); //Printing complete tier information
console.log(docs.tiers[0].offers[0]) //Just printing Object ID, not taking data from offers table
})
})
Problem is it is just populating tiers and not offers. How do I go deeper? Corresponding example is here:
https://github.com/paulcsmith/mongoose-currency/blob/master/node_modules/mongoose/examples/population-across-three-collections.js
I had a similar problem, I have a song that haves mixes (Next songs) and also Artists. In here first I find the song by name, then I populate the songs that go next and also their Artists, on the song that goes next I populate the song and also the Artist information.
Hope it helps.
Song.find({songName: req.params.id})
.lean()
.populate({ path: 'songMixs songArtist' })
.exec(function(err, docs) {
var options = {
path: 'songMixs.nextSong',
model: 'Song'
};
if (err) return res.json(500);
Song.populate(docs, options, function (err, projects) {
var options2 = {
path: 'songMixs.nextSong.songArtist',
model: 'Artist'
};
Artist.populate(docs, options2, function (err, projects) {
res.json(projects);
});
//res.json(projects);
});
});

Cannot applying find() method with Native MongoDB becaus of ID type

I have a function that is needed to get results.
When I give 1 as _id filter everything is OK.
collectionPersonnel
.find({ '_id' : 1 })
.toArray(function (err, personnel) {
console.log(personnel);
});
If I give filter another way for instance user[0]['personnel_id'] -that is store 1- then I get only [] result;
collectionPersonnel
.find({ '_id' : user[0]['personnel_id'] })
.toArray(function (err, personnel) {
console.log(personnel);
});
And then I've tried another way. But it doesn't work because I used a string(user[0]['personnel_id']) instead of an ObjectID.
var ObjectID = require('mongodb').ObjectID;
var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
What should I do?
Edit
All of my codes are below;
module.exports = {
show: function(req, res) {
User.native(function(err, collectionUser) {
if(err) {
console.log("There is no exist a User by current_id");
};
collectionUser
.find({'_id' : req.param('id')})
.toArray(function (err, user) {
Personnel.native(function(err, collectionPersonnel) {
if(err) {
// handle error getting mongo collection
console.log("There is no exist a Personel by current _id");
};
if(!collectionPersonnel) {
console.log("There is no exist a Personel by current _id");
};
// var ObjectID = require('mongodb').ObjectID;
// var personnelPK_Hex = (user[0]['personnel_id']).toHexString();
// var personnelPK = ObjectID.createFromHexString(personnelPK_Hex);
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});
});
});
});
}
};
And console's output is;
[]
Solved
Just like apsillers's said. I had given a numeric _id to collection, incorrectly.
I've fixed _id value and everything is OK.
Thank you all...
user[0]['personnel_id'] might be a string. For Mongo, "1" is different from 1, which is why your literal number 1 worked, but your variable (which holds a string) does not.
Instead, try using a unary plus to convert the string to a number: +user[0]['personnel_id'].
try to use like user[0].personal_id instead of user[0]['personnel_id'] please provide your schema design that would be better to figure out what exactly you are missing.
i tried like this
collectionPersonnel
.find({ '_id' : user[0].personnel_id })
.toArray(function (err, personnel) {
console.log(personnel);
});

Mongoose searching FindOne with multiple arguments

My first attempt at building something with Angular + express + mongodb, so I'm probably going about this completely the wrong way. Express is being used to serve up json. Angular then takes care of all the views etc.
I'm using Mongoose to interact with Mongo.
I have the following database schema:
var categorySchema = new mongoose.Schema({
title: String, // this is the Category title
retailers : [
{
title: String, // this is the retailer title
data: { // this is the retailers Data
strapLine: String,
img: String , // this is the retailer's image
intro: String,
website: String,
address: String,
tel: String,
email: String
}
}
]
});
var Category = mongoose.model('Category', categorySchema);
and in Express I have a couple of routes to get the data:
app.get('/data/categories', function(req, res) {
// Find all Categories.
Category.find(function(err, data) {
if (err) return console.error(err);
res.json(data)
});
});
// return a list of retailers belonging to the category
app.get('/data/retailer_list/:category', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({ _id: req.params.category }, function(err, data) {
if (err) return console.error(err);
res.json(data)
});
});
The above works - I'm just having big problems trying to get at a single retailer. I'm passing the category, and retailer id through... I've tried all sorts of things - from doing a find on the category, then a findOne on the contents within... but I just cant get it to work. I'm probably going about this all wrong...
I found this thread here: findOne Subdocument in Mongoose and implemented the solution - however, it returns all my retailers - and not just the one I want.
// Returns a single retailer
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({_id: req.params.category , 'retailers.$': 1}, function(err, data) {
console.log(data);
if (err) return console.error(err);
res.json(data)
});
});
Thanks,
Rob
Now that I see your full filter/query, you should be able to use the array positional operator in this case as part of the projection rather than doing client side filtering:
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({
/* query */
_id: req.params.category ,
'retailers._id' : req.params.id
},
{ /* projection */
"retailers.$" : 1
},
function(err, data) {
var retailer = _.where(data.retailers , { id : req.params.id });
if (err) return console.error(err);
res.json(retailer)
});
});
For the { "retailers.$" : 1 } to work properly, the query must include a field from an element in the array. The $ operator returns the first match only.
The guys next door use Mongo + Express and gave me some pointers: they explained to me how mongo worked, and advised I should use underscore.js to assist with my filter.
They said I needed to pull the entire category out - and then run the filter. I don't strictly need , 'retailers._id' : req.params.id} but they said to leave it in as it guaranteed that the category would only be returned if an item within it contained that information. I still don't really know why or how... So can't really mark this as solved.. it it solved, but I don't really get why as yet - so will do more reading :)
app.get('/data/retailer_detail/:category/:id', function(req, res) {
//pass in the category param (the unique ID), and use that to do our retailer lookup
Category.findOne({_id: req.params.category , 'retailers._id' : req.params.id}, function(err, data) {
var retailer = _.where(data.retailers , { id : req.params.id });
if (err) return console.error(err);
res.json(retailer)
});
});

find results of attributes in mongodb are always undefined

I really really need help in this. I am using node.js with mongodb and mongoose. So far I've managed to create a schema and save those into my database.
var Bericht = new Schema({
name : String
, mail : String
, betreff : String
, inhalt : String
, datum : Date
});
var Bericht = mongoose.model('Bericht', Bericht);
I habe a html formular where I can transmit with misc. fields data, by querystring I converting those into readable strings
var bericht_data = {
name: tempo.Name
, mail: tempo.Mail
, betreff: tempo.Betreff
, inhalt: tempo.Inhalt
};
var testoro = new Bericht(bericht_data);
testoro.save(function (err) {
if (!err) console.log('Success!');
});
so tempo.Name for example is a string and it also successful in saving it.
So far I can save all data from this formular into my mongodb.
Now the very problem: I want the data back as string to handle for dynamic html.
To get the info into my console, I use
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
console.log(docs);
// process.exit();
}
else { throw err;}
}
);
The console gives me all data which was ever saved in my schema Bericht excluding the long _id stuff. Sample output:
[ { name: 'Hans', mail: 'hans#wurst.de', betreff: 'I lost my wurst', inhalt: 'look at me, I am amazing' } ]
That's just one, normally there would be a huge amount of data.
The idea is right now to extract only the name into a string like "Hans". I want to get this name into a var, but hell it seems impossible!
I've tried
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
console.log(docs.name);
// process.exit();
}
else { throw err;}
}
);
But the I get only "undefined" delivered. I appreciate your help!
Take a look at Mongoose QueryStreams. I haven't used it myself, but I've modified their example code to fit your Model, to give you an idea of how it might work in practice:
var stream = Bericht.find().stream()
, names = []
, i;
function closeHandler() {
console.log(JSON.stringify(names));
};
stream.on('data', function (doc) {
if (doc.name) {
names.push(doc.name);
}
})
stream.on('error', function (err) {
// handle err
})
stream.on('close', closeHandler)
Mongoose find return an array of documents so you should try the following:
Bericht.find(
{},
{ '_id': 0},
function(err, docs) {
if (!err){
for(var i=0; i<docs.length; i++)
{
console.log(docs[i].name);
}
// process.exit();
}
else { throw err;}
}
);

Return mongojs query result from function

I made the function below for getting usernames from ids. It is not working well.
I can write console.log(result.first_name); within the query function, and the usernames shows up in my terminal, but not the browser. I tried adding “return 'something';” at the end of the function, to see if that showed up in the browser – It did. How can I write the function so that the query result is returned?
function (global function in app.js)
function usernameFromId(id, callback){
db.users.findOne({ _id: ObjectId(id.toString()) }, function(err, result) {
var first_name = result.first_name;
console.log(first_name); // names show up in the console…
callback(first_name);
});
};
page handler (in app.js)
app.get('/books', function(req, res){
function timeSince(dato){
moment.lang('nb');
return moment(dato).fromNow();
};
db.books.find().sort({ added:-1 }, function(err, docs) {
var books = docs;
db.activity.find().limit(9).sort({ time:-1 }, function(err, docs) {
var activity = docs;
res.render('books', {
books: books,
activity: activity,
timeSince: timeSince,
usernameFromId: usernameFromId
})
});
});
});
template (books.jade)
- each a in activity
p=usernameFromId(a.user_id, function(name){return name;})
No because of the asynchronous nature of JavaScript. I have added some comments to your code to indicate the actual order of execution. This is why you are getting the error.
function usernameFromId(id){
var id = id.toString(); // 1
db.users.findOne({ _id: ObjectId(id) }, function(err, result) {
var first_name = result.first_name; // 3
});
return first_name; // 2
};
Edit: you probably want something like the following
function usernameFromId(id, callback){
var id = id.toString();
db.users.findOne({ _id: ObjectId(id) }, function(err, result) {
var first_name = result.first_name;
callback(first_name);
});
};
Okay, I found a solution. Not sure whether it’s any good, but it works. No need for a function.
page handler (in app.js):
app.get('/books', function(req, res){
db.activity.find().limit(9).sort({ time:-1 }, function(err, docs) {
var activity = docs;
db.users.find(function(err, docs) {
var users = docs;
res.render('books', {
page_title:'books',
activity: activity,
users: users
})
});
});
});
template (books.jade):
- each a in activity
- for u in users
- if (a.user_id == u._id.toString())
| #{u.first_name}

Resources