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);
});
Related
I am using Node and Mongoose, and trying to set an array of ISODate elements:
"visitLog" : [
ISODate("2017-10-22T22:43:49.571Z"),
ISODate("2017-10-22T22:44:39.572Z"),
ISODate("2017-10-22T23:35:36.111Z"),
ISODate("2017-10-22T23:48:26.516Z"),
ISODate("2017-10-22T23:50:33.378Z"),
ISODate("2017-10-22T23:53:56.227Z"),
ISODate("2017-10-22T23:57:20.986Z")
]
So I had an existing schema where visitLog field did not existed, added new field to a schema - visitLog: [ {type: Date, default: '' }],and it worked - the result is what you see above.
But when I created a new document with updated schema that already has an empty array in it - "visitLog" : [ ] , $push just stopped working.
Here is mongoose query, if needed:
// conditions is a ternary operator that checks whether req.body username
// is an email or not, and puts needed condition to a query
var conditions = (!/^[a-zA-Z0-9\-\_\.\+]+#[a-zA-Z0-9\-\_\.]+\.[a-zA-Z0-9\-\_]+$/.test(req.body.username)) ? ' {email: req.body.username } ' : ' {username: req.body.username } ';
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { upsert: true };
User.findOneAndUpdate(conditions, fieldsToSet, options, function(err, user) { ...
The working document was created in mongo console, while the second was generated on a server, but I can't how can this make any difference.
Using $push shuld work with empty arrays. Can someone explain what's wrong here?
Thank you.
Edit
It figures that using findByIdAndUpdate without conditions works for both documents:
var fieldsToSet = {
$push: {
visitLog: new Date().toISOString(),
}
};
var options = { new: true };
req.app.db.models.User
.findByIdAndUpdate(req.user.id, fieldsToSet, options, function(err, user) {
You can do with the following query.
User.findOne(condiitons, (err, user) => {
if (user) {
var date = new Date().toISOString();
user.visitLog.push(date);
user.save();
...
}
});
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!' });
});
});
//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'
})
});
});
I would like to ask if there is anyone getting the same response on JSON format:
Objectdata: "User is not authorized"headers: (name) {status: 403statusText: "Forbidden"
Scenario:
User A post a product and add comment on the product.
Result: Successful.
User B comment on the same product:
Result: User is not authorized.
The code I'm using to update the product comment is here:
applicationname/`
// Add comment to Product
$scope.comment = function(){
// console.log("name: ",$scope.user);
// console.log("textarea: ",this.commentarea);
var comment = {
name: $scope.product.user.displayName,
text: this.commentarea
};
$scope.product.comments.push(comment);
$scope.product.$update(function() {
console.log('success update');
}, function(errorResponse) {
console.log('success error', errorResponse);
});
};
This is the server side.
'use strict';
/**
* Module dependencies.
*/
var init = require('./config/init')(),
config = require('./config/config'),
mongoose = require('mongoose'),
chalk = require('chalk');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
if (err) {
console.error(chalk.red('Could not connect to MongoDB!'));
console.log(chalk.red(err));
}
});
// Init the express application
var app = require('./config/express')(db);
// Bootstrap passport config
require('./config/passport')();
// Start the app by listening on <port>
app.listen(config.port);
// Expose app
exports = module.exports = app;
// Logging initialization
console.log('MEAN.JS application started on port ' + config.port);
If your Products schema looks like this:
var ProductSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
comments: [{
type: String,
default: '',
trim: true
}]
});
And you have restricted your products route in your app/routes/products.server.routes.js file like so:
app.route('/products/:productId')
.get(products.read)
.put(users.requiresLogin, products.hasAuthorization, products.update)
.delete(users.requiresLogin, products.hasAuthorization, products.delete);
Then a non-authorized user cannot add a comment because they can't update the Product record.
You probably want to create a separate CommentsSchema and use the Mongoose ObjectId type to create a one-to-many relationship with the product:
var CommentSchema = new Schema({
product: ObjectId,
content: {
type: String,
default: '',
trim: true,
required: 'Content cannot be blank'
},
})
That will preserve the security of your product and allow non-authorized users to comment, but would require you to do slightly more complex queries to get your comments in your product view.
I have two mongoose schemas as follow:
var playerSchema = new mongoose.Schema({
name: String,
team_id: mongoose.Schema.Types.ObjectId
});
Players = mongoose.model('Players', playerSchema);
var teamSchema = new mongoose.Schema({
name: String
});
Teams = mongoose.model('Teams', teamSchema);
When I query Teams I would to get also the virtual generated squad:
Teams.find({}, function(err, teams) {
JSON.stringify(teams); /* => [{
name: 'team-1',
squad: [{ name: 'player-1' } , ...]
}, ...] */
});
but I can't get this using virtuals, because I need an async call:
teamSchema.virtual('squad').get(function() {
Players.find({ team_id: this._id }, function(err, players) {
return players;
});
}); // => undefined
What is the best way to achieve this result?
Thanks!
This is probably best handled as an instance method you add to teamSchema so that the caller can provide a callback to receive the async result:
teamSchema.methods.getSquad = function(callback) {
Players.find({ team_id: this._id }, callback);
});