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!' });
});
});
Related
I want to define a put method by using findOneAndUpdate() on a mongoDB object using AngularJS. I am able to successfully do GET and POST operations but I am having difficulty defining PUT. Below is my db object defined in app.js file:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/testing23');
var idObj = Schema({
_id: String,
name : {
firstname : String,
lastname : String
},
phones : [Number],
emails : [String],
friends : [String]
});
var Error = mongoose.model('Error', idObj );
My GET and POST are below:
app.get('/api/info',function(req,res){
Error.find(function(err,infos){
if(err)
return res.send(err);
return res.json(infos);
});
});
app.post('/api/info',function(req,res){
Error.create(req.body, function(err,infos){
if(err)
return res.send(err);
return res.json(infos);
});
});
For PUT I am using below method but it is not working:
app.put('/api/infos/:id',function(req,res){
Error.findOneAndUpdate({_id: req.params.id},req.body,function(err,infos){
if(err)
return res.send(err);
return res.json(infos);
});
});
How can I successfully do a PUT operation?
As per the Mongoose Docs your find and modify command should look like the following
Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
For the example you provided and say you want to update the name, it would be
Error.findOneAndUpdate({_id: req.params.id},{ $set: { name: req.body }},{new: true},function(err,updatedInfos){
if(err)
return res.send(err);
return res.json(updatedInfos);
});
Using {new:true} means the updated document gets returned.
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]})
I using angluarjs with mongodb.
I have schema is called array based schema.
schema structure :
var Schema = new Schema({
UnitId: String,
UnitName: String ,
Details1:[{
Details1ID:String,
Name:String,
Amount:Number
}],
Details2:[{
Details2ID:String,
Name:String,
Amount:Number
}],
Details3:[{
Details3ID:String,
}],
I want query for inserting the req.body for only Details3.
how to do this?
NOTE:Req.body is Dynamic value
first, you need to add { strict : false } options to your schema
var schema = new mongoose.Schema({
// ..
}, {
strict: false
})
module.exports = mongoose.model('MyModel', schema, 'myModel');
then create model with partial data
// Node.js server side
var model = new MyModel({
// UnitId: "xxx",
Details3: [...whatever]
});
model.save((error, data) => {
console.log("model has been saved", data);
});
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);
});
})
//Here is model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
// Task schema
var taskSchema = mongoose.Schema({
tasktype : {type: String},
createdon : {type: Date, default: Date.now},
createdby : {type: Schema.Types.ObjectId,ref: 'User'},
visitedby : [{type: Schema.Types.ObjectId,ref: 'User'}],
taskinfo : [{ isactive:Boolean, taskobject:String, taskdetails:String, iscompleted:Boolean}]
});
module.exports = mongoose.model('Task', taskSchema);
// route
var Task = require ('../models/task');
var User = require ('../models/user');
var config = require ('../../config');
module.exports = function(app, express) {
var api = express.Router();
api.post('/tasks', function (req, res) {
var task = new Task({
// ...
tasktype : req.body.tasktype,
taskinfo : req.body.taskinfo,
});
task.save(function(err){
if(err){
res.send(err);
return;
}
res.json({message:'Task has been created'})
});
return api
}
While all other fields getting saved but the one with array with multiple fields always return blank like "taskinfo : [ ] "
The post method is REST API to post a task into mongoose database, for array with single field everything working fine but array with multiple field is not getting saved, someone please help me here.
Basic help will be fine, just please teach me how to save "multiple field array".
Mongoose doesnot always require subdocument structure and this can be achieved by the above model, please dont advice to use subdocument structure, I want to learn this.
Thank You.
I think if taskinfo has a multiple values and you want to save it as embedded document inside task document. You should have different document of task info. So,you can save like that
var TaskInfoSchema = require("taskInfo.js").TaskInfoSchema
var taskSchema = mongoose.Schema({
tasktype : {type: String},
createdon : {type: Date, default: Date.now},
createdby : {type: Schema.Types.ObjectId,ref: 'User'},
visitedby : [{type: Schema.Types.ObjectId,ref: 'User'}],
taskinfo : [TaskInfoSchema]
});
module.exports = mongoose.model('Task', taskSchema);
And now you will have different document as task info like
var taskInfo = mongoose.Schema({
isactive:{type:Boolean},
taskobject:{type:String},
taskdetails:{type:String},
iscompleted:{type:Boolean}
});
var TaskInfo = mongoose.model('TaskInfo', taskSchema);
module.exports.TaskInfo = TaskInfo
module.exports.TaskInfoSchema = taskSchema
When you will save task document,
Var TaskInfo = new TaskInfo({
isactive:true,
taskobject:"",
taskdetails:"",
iscompleted:true
})
var task = {};
task.tasktype = req.body.tasktype;
you can push it
task.taskinfo = [];
for (var i = 0; i < req.body.taskInfo.length; i++) {
var taskInfo = new TaskInfo(req.body.taskInfo[i]);
task.taskinfo.push(taskInfo);
}
Then you will save task document
var taskObj = new Task(task);
taskObj.save(function (err) {
if (err) {
res.send(err);
return;
}
res.json({
message: 'Task has been created'
})
});
});