How can I include data from another collection in my mongoose object? - angularjs

I am building an app with mongoDB and NodeJS with an Angular front end. I currently have users creating listings and then other users responding with bids within those listings, but want to include data of those responders. I am having a hard time including that user data in the bid create function and not sure why its not pulling.
Here is the listing schema
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var Bid = require('./bid');
var ListingSchema = new Schema({
topic: String,
description: String,
budget: String,
location: String,
req1: String,
req2: String,
req3: String,
created: String,
dateReq: String,
uid: String,
bids: [Bid.schema]
})
This is how I currently create new listings
function create(req, res) {
db.User.findById(req.user, function (err, user) {
if (err) {console.log(err);}
var newListing = new db.Listing(req.body);
newListing.uid = user._id
newListing.save(function (err, savedListing) {
if (err) {
res.status(500).json({ error: err.message });
} else {
user.listings.push(newListing);
user.save();
res.json(savedListing);
}
});
});
};
This is for new bids. For some reason, the db.User information is not getting pulled and my console log shows a blank object. (Yes I commented it out)
function create(req, res) {
// db.User.findById(req.user, function (err, user) {
// console.log(req.user);
// if (err) {console.log(err);}
db.Listing.findById(req.params.listingId, function(err, foundListing) {
var newBid = new db.Bid(req.body); // add data validation later
// newBid.uid = user._id
foundListing.bids.push(newBid);
foundListing.save(function(err, savedBid) {
res.json(newBid);
});
});
});
};

try using user_id as a Object reference and populate it when needed your schema should be somewhat like this
var ListingSchema = new Schema({ topic: String,description: String, budget: String, location: String, req1: String, req2: String, req3: String, created: String, dateReq: String,//THIS CREATES A REFERENCE TO THE SCHEMA USER AND TO USE THIS YOU CAN POPULATE IT.. uid: {type:Schema.type.ObjectId,ref:User}, bids: [Bid.schema]})

Related

Mongoose models' save() won't update empty array

I have an array (bookedby) in a Mongoose model defined like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BarSchema = new Schema({
date: {
type: Date,
required: true
},
barid: {
type: String,
required: true
},
bookedby: {
type: [String],
required: true
},
});
module.exports = mongoose.model('Bar', BarSchema);
I update it with following function, called by a nodejs express router:
const Bars = require("../../models/bars");
const { getToday } = require('../../utils');
module.exports = function(req, res) {
const { barid } = req.body;
const { username } = req.user;
const date = getToday();
if( !barid ) return res.json({ success: false, error: 'Please specify parameter \'barid\'.'})
Bars.findOne({ barid, date }, function (err, bar) {
if (err) return next(err);
if (!bar || bar.bookedby.indexOf(username) === -1) return res.json({ error: `Bar is not booked yet.` });
// Someone booked the bar
const index = bar.bookedby.indexOf(username);
bar.bookedby.splice(index, 1);
bar.save(err => {
if (err) res.json({ error: `Error saving booking.` });
else res.json({ success: true });
});
});
};
Everything works fine, except when I remove the last item from the bookedby array. Then the save() function doesn't update the database. The last item remains there. I guess it has something to do with mongodb optimizing empty arrays, but how can I solve this?
According to the Mongoose FAQ:
http://mongoosejs.com/docs/faq.html
For version >= 3.2.0 you should use the array.set() syntax:
doc.array.set(3, 'changed');
doc.save();
If you are running a version less than 3.2.0, you must mark the array modified before saving:
doc.array[3] = 'changed';
doc.markModified('array');
doc.save();

in whole process i need to try enter n no. of questions and n no. of choices are save in mongoshell

1. schema code
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let presenterschema = new Schema({
Name: String,
Organization: String,
Email: String,
phone: Number,
question: [{
question: String,
choice: [{
choice_a: String,
choice_b: String,
choice_c: String,
choice_d: String,
}],
}],
});
module.exports = mongoose.model('presenter', presenterschema);
Email using as unique keyword to find out those email address which was already in db and push question and choices to that email id.
1. node.js code
app.post('/get_questio', function (req, res) {
presenter.findOne({ Email: req.body.Email }, function (err, data) {
question = req.body.question;
choice = req.body.choice;
choice_a = req.body.choice_a;
choice_b = req.body.choice_b;
choice_c = req.body.choice_c;
choice_d = req.body.choice_d;
data.question.push({ question })
data.question.choice.push({ choice_a, choice_b, choice_c, choice_d })
data.save(function (err, data) {
if (err) {
res.send("something went wrong " + err)
} else {
res.send(data)
}
})
})
})
actual i tried create a quiz application.

Populating data from referenced models in different modules in MEAN.JS

I am absolutely new to the MEAN stack, and I am using the MEAN.js(ver 0.4.2) generator for my project.
I am using the default users module and created a new module 'Topics' using the module generator. I have a basic role based login system using the users module where users can sign up and see/edit their profiles. In the profile, there is a reference to the topics module's mongoose model called 'Topics'.
topic.server.model.js looks like this(this is the schema for the topics) :
//Topic Schema
var TopicSchema = new Schema({
.......
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Topic', TopicSchema);
The content from this model can access the data from the users model. But the i cant get the items to show from the topics model, when i am referencing them from the users module.
My users model has this in the schema :
var UserSchema = new Schema({
......
interest: [{
type: Schema.Types.ObjectId,
ref: 'Topic'
}],
skills: [{
type: Schema.Types.ObjectId,
ref: 'Topic'
}]
});
mongoose.model('User', UserSchema);
I am trying to populate the data from topics using the following middleware :
exports.userByID = function (req, res, next, id) {
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(400).send({
message: 'User is invalid'
});
}
User.findById(id, '-salt -password').populate('interest', 'name').populate('skills', 'name').exec(function (err, user) {
if (err) {
return next(err);
} else if (!user) {
return next(new Error('Failed to load user ' + id));
}
req.model = user;
next();
});
};
I would need a little guidance as to how do i get the data in front end to show, something like {{user.interest.name}}.
Edit
In the users.profile.server.controller, the json is not getting created from this :
exports.me = function (req, res, next) {
var id = req.user._id;
User.findOne({
_id: id
}).populate('interest', 'name').populate('skills', 'name').exec(function(err, userData) {
if (err) return next(err);
if (!userData) return next(new Error('Failed to load User ' + id));
res.json(userData || null);
next();
});
};
Getting the following error in the terminal :
GET /api/users/me 400 22.173 ms - -
Error: Can't set headers after they are sent.

Output all documents in mongoose

I am using mongoose ODM and have a schema which looks like this:
var banSchema = new Schema({
userid: { type: String, required: true, unique: true },
name: String,
groupid: String,
reason: String,
timestamp: Date
});
I want to output every single user id from all documents in the collection. I am using this query to obtain the userid objects. However I cannot seem to get the full list automatically. I have to manually enter the object number as seeen below:
bot.onText(/\/sync/i, function (msg) {
var fromId = msg.from.id;
var chatId = msg.chat.id;
if (fromId == config.sudo) {
console.log('Sudo Confirmed And Authorized!');
Ban.find({}, function (err, obj) {
console.log(obj[0].userid); // Returns A Single ID
console.log(obj[1].toObject().userid); // Returns a different ID
bot.sendMessage(chatId, obj[1].toObject().useridid);
});
} else {
console.log('Someone Is Trying To Act Like Sudo! *sigh*');
bot.sendMessage(chatId, 'You Are Not A Mod!');
}
});
This however does not return a full list of id's as I want. How could I solve this issue?
The code above is for a telegram bot which on a /sync command it should return a message with all ids from the collection.
Telegram bot API Limits
Due to the API limits, the entire output should be in a single message.
var query = Ban.find({}).select({
"userid": 1,
//Add more column fields here
"_id": 0 //Ensures _id is not displayed
});
var arr = [];
query.exec(function (err, results) {
if (err) throw err;
results.forEach(function (result) {
arr.push(result.userid);
// Add more column fields here;
});
var fixedJoin =arr.join("\n");
console.log(fixed);
bot.sendMessage(chatId, 'List\n\n' + fixedJoin);
});
The easiest way to get all values of a particular field across all docs in the collection is to use distinct:
Ban.distinct('userid', function (err, userids) {
// userids is an array containing all userid values in the collection.
// string.join into a single string for the message.
bot.sendMessage(chatId, 'USER IDs\n\n' + userids.join('\n'));
});
Use this syntax
Ban.find({}).
select('userid').
exec(function(err, result) {
//result is array of userid of all document
});
You can use this syntax:
Ban.find({}, 'userid', function(err, users) {
users.forEach(function(user) {
console.log(user);
bot.sendMessage(chatId, 'users \n' + user);
});
})

Mongoose model with array logic

I'm currently training with Mongoose and to do so I'm building a little messaging app.
I have a collection of user, here is the User.js :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String,
password: String
});
module.exports = mongoose.model('User', UserSchema);
now I want to write a chatroom model that should contain a list of users, how should I proceed ? Here is my current Chatroom.js :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ChatroomSchema = new Schema({
name: String,
password: String,
members: ???
});
module.exports = mongoose.model('Chatroom', ChatroomSchema);
Finally I would like to know how to post a user in that members array when creating a chatroom, here is my route code for /chatroom :
router.route('/chatroom')
.post(function(req, res) {
var chatroom = new Chatroom();
chatroom.name = req.body.name;
chatroom.password = encrypt(req.body.password,chatroom.name);
chatroom.members = ???;
chatroom.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Chatroom created!' });
});
});
Is there a specific way to bind a user to the members array or should I just define members as an array of string :
members : {username:String}
Population would be ideal in your case. From the docs:
Population is the process of automatically replacing the specified
paths in the document with document(s) from other collection(s).
Population will seamlessly help you bring data from the Users collection into your Chatroom model. Consider the following example to illustrate this approach:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ChatroomSchema = new Schema({
name: String,
password: String,
members: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});
module.exports = mongoose.model('Chatroom', ChatroomSchema);
In your chatroom schema definition, you add a list of primary surrogate keys to each object, called ObjectId, referenced as _id in the data by surrounding the field definition members in square brackets to get this functionality. These will be the keys used to refer to documents in the User collections.
Note:- When you define the references, the ref attribute must match exactly the model name in your model definition else you will get an error (suppose you refer to a non-existing Member model or Users)
MissingSchemaError: Schema hasn't been registered for model "Member"..
Reading the data
This is where Mongoose population shows how easy and fast it is to makes reads of documents very straightforward through its populate() function. So for instance, to show the referenced users in a chatroom, call the populate() method with the name of that field in a string as a parameter e.g.
Chatroom.findOne({"_id": chatId})
.populate("members")
.exec(err, chats) { ... }
Writing data
When you save data for the Chatroom model, you will also need to save the references to the users. For instance, when a new Chatroom is created, you'll need an array of User references saved as the members field:
router.route('/chatroom')
.post(function(req, res) {
var chatroom = new Chatroom();
var usersIds = ["54b5659536cd5250a3a93bd3", "54b5659836cd5250a3a93bd4"]; // <-- an array with members ids, for example.
chatroom.name = req.body.name;
chatroom.password = encrypt(req.body.password,chatroom.name);
chatroom.members = usersIds;
chatroom.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Chatroom created!' });
});
});
Try with referenced documents
Chatroom.js
var ChatroomSchema = new Schema({
name: String,
password: String,
members: [Schema.Types.ObjectID, ref = 'user']
});
Controller
router.route('/chatroom')
.post(function(req, res) {
var chatroom = new Chatroom();
chatroom.name = req.body.name;
chatroom.password = encrypt(req.body.password,chatroom.name);
chatroom.members = req.user; // if the user is authenticated
chatroom.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Chatroom created!' });
});
});

Resources