some error in using $push in mongodb - node.js

my Schema is
var User = new mongoose.Schema({
//general information
name : {type:String},
email : {type : String},
number : {type : String},
password : {type:String},
//featured information
path: { type: String},
dob : {type:String},
gender : {type : String},
blood_group : {type:String},
marital_status : {type : String}
});
module.exports = mongoose.model('user',User);
i want to use update some details by-
app.post('/contactinfo',function (req,res) {
var name = req.body.name;
var number = req.body.number;
var email = req.body.email;
User.update({_id : userID},{
$push : {
name : name,
number : number,
email : email
}
},{new : true },function (err,result) {
if(err){
console.log(err);
}
else{
console.log(result);
res.send({status : "success" , message : "Details updates"});
}
});
});
I don't define array anywhere
but the problem is that is show error on updating
{ MongoError: The field 'name' must be an array but is of type string in document {_id: ObjectId('5a0880e2d767e8131807e7f4')}
I am stuck here
please someone help me in solving this error

You just have to change your $push to $set. That's it.

Related

Mongoose virtuals in array of subdocument

Is there a way to "get" the value a document's field in the subdocuments?
book_id is in the main document,how to get the value of it here
'''
const ExtraElements_Schema = new Schema({
label : {type : String, requires : true},
page : {type : Number},
id_resource : {type : Number, required : true},
description : {type : String}
},{toJSON : {virtuals : true , getters : true}})
ExtraElements_Schema.virtual('path').get(function(){
const host = global.gConfig.thisServerHost;
return `${host}/${this.book_id???}/${this.id_resource}`
})
const Extra_Schema = new Schema({
label : {type : String, required : true},
book_id : {type : Number},
id_extra : {type : Number, required : true},
extras : [ExtraElements_Schema]
})
You can use virtuals for this too.
ExtraElements_Schema.virtual('book', {
ref: bookTableName,
localField: 'book_id',
foreignField: '_id', // Change this if it's not the id that is saved
justOne: true
});
And one thing that bugged me a little I couldn't see the virtuals with console.log I should always use console.log(model.toJSON()) to see the virtuals

Mongoose Finding data in Sub document

I have this model
//user notif schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserNotifSchema = new mongoose.Schema({
NotifType : {type : Number},
NotifData : {
User_source_id : {type : Schema.Types.ObjectId, ref : 'User'}, // for course, forking
Course_id : {type : Schema.Types.ObjectId, ref : 'Course'}, // for course
UserFile_id : {type : Schema.Types.ObjectId, ref : 'UserFile'} // for forking
},
NotifTarget : [
{type : Schema.Types.ObjectId, ref : 'User'}
],
Created_at : {type : Date, required : true, default : Date.now},
});
var UserNotif = mongoose.model('UserNotif', UserNotifSchema);
module.exports = UserNotif;
I create a model that contains user notification by NotifTarget. I want to get some notif to specific user and doing like this
var user_id = req.session.userLogin.UserId;
NotifModel.find({'NotifTarget' : user_id})
.populate('NotifTarget')
.exec(function(err, doc){
if (err){
res.send(err);
}
else{
res.send(doc);
}
})
This is ok when there only one array user_id in NotifTarget but return empty array when I give multiple data in NotifTarget. Are there any solution for this?

Deleting subdocuments using mongoose returning error?

I want to delete all the sub-documents of my collection.
mongoose schema :
//productSchema
var pdtSchema = new Schema({
"productId" : {type : String},
"product" : {type : String},
"item no" : {type : String},
});
var shopSchema = new Schema({
"providerId" : {type : String},
"provider" : {type : String},
"products" : [pdtSchema]
}, { collection:"shopdetails" });
module.exports.Shops = mongoose.model('Shops',shopSchema);
module.exports.Products = mongoose.model('Products',pdtSchema);
I have stored a bulk of data inside the collection and I need to delete all the products(that is the whole pdtSchema data).
code:
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findById({"providerId" : providerId},function(err, doc) {
console.log(doc.products) // returns whole products here...
doc.products.remove();
doc.save(function(err,data){
res.json({"msg":"deleted"});
});
});
});
error:
(node:16351) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): ValidationError: CastError: Cast to ObjectID failed for value "[Function]" at path "_id"
Use the $unset operator which deletes the products field with the findOneAndUpdate() method. Using the traditional approach of first
retrieving the document with findById() only works with a valid ObjectId, in your case you are only providing a non-ObjectId string, hence the error.
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findOneAndUpdate(
{ "providerId": providerId },
{ "$unset": { "products": "" } },
{ "new": true }
function(err, doc) {
console.log(doc) // returns modified doc here...
res.json({"msg": "Field deleted"});
}
);
});
If you want to keep the array field but remove all its elements, use $set as
router.post('/delete',function (req,res) {
var providerId = req.body.providerId;
model.Shops.findOneAndUpdate(
{ "providerId": providerId },
{ "$set": { "products": [] } },
{ "new": true }
function(err, doc) {
console.log(doc) // returns doc with empty products here...
res.json({"msg": "Products deleted"});
}
);
});
This is because you are saving "providerId" in shopSchema as type String, even though it is a mongoose object.
So, comparing a string type against a mognoose ObjectId type gives a cast error.
Instead do this,
var shopSchema = new Schema({
"providerId" : {
type : Schema.ObjectId
ref : schema which they are a reference to},
"provider" : {type : String},
"products" : [pdtSchema]
}, { collection:"shopdetails" });
But, I think if providerId refers to a shop Id, then it should be _id only.
model.findById() works with _id

Mongoose- How to use discriminators in subdocument

I want the output to be like this
var FeedSchema = new Schema({
timestamp : {type : String, required : true},
feed_type_code : {type : Number, required : true},
gender : {type : String, required : true},
feed_item : Article || Tip || etc.
}
Hence, I understand I have to use discriminators. I followed the following SO answer
Here is what I did:
var feed_type = {discriminatorKey : 'feed_item'};
var FeedSchema = new Schema({
timestamp : {type : String, required : true},
feed_type_code : {type : Number, required : true},
gender : {type : String, required : true}
}, feed_type);
var TipSchema = new Schema({
tip : {type : String, required : true},
subtip : {type : String, required : true},
display_count : {type : Number},
likes : {type : Number}
}, feed_type);
var ArticleSchema = new Schema({
title : {type : String, required : true},
english_title : {type : String, required : true},
image_url : {type : String, required : true},
article_text : {type : String, required : true},
english_article_text : {type : String},
author : {type : String},
english_author : {type : String}
}, feed_type);
Here is how I am saving the document:
var article = new Article({
title : req.body.title,
english_title : req.body.english_title,
image_url : req.body.image_url,
article_text : req.body.article_text,
english_article_text : req.body.english_article_text,
author : req.body.author,
english_author : req.body.english_author
});
var feed = new Feed({
gender : req.body.gender,
timestamp : moment().valueOf(),
feed_type_code : 9002,
feed_item : article
});
feed.save(function(err, doc){
if(err){
res.json({success : -1});
return;
}
res.json({success : 1, feed : doc});
});
I am not getting the article output for this:
{
"success": 1,
"feed": {
"__v": 0,
"gender": "female",
"timestamp": "1481460218959",
"feed_type_code": 9002,
"_id": "584d49faa6ff3a23bc868ab3"
}
}
I am new to Nodejs. I would appreciate if you can point out the error.
in the model file add these lines
var Feed = mongoose.model('Feed', FeedSchema, 'feed');
var Article = Feed.discriminator('Article', ArticleSchema);
var Tip = Feed.discriminator('Tip', TipSchema);
module.exports = {
Feed : Feed,
Article : Article,
Tip : Tip
}
This is how you save the document. You don't need to create a separate Feed object.
var article = new Article({
gender : req.body.gender,
timestamp : moment().valueOf(),
feed_type_code : 9002,
title : req.body.title,
english_title : req.body.english_title,
image_url : req.body.image_url,
article_text : req.body.article_text,
english_article_text : req.body.english_article_text,
author : req.body.author,
english_author : req.body.english_author
});
article.save(function(err, doc){
if(err){
console.log(err);
res.json({success : -1});
return;
}
res.json({success : 1, feed : doc});
});

Mongoose doesn't create model object with array

I'm working on a project where I have the following mongoose schema:
module.exports = mongoose.model('Env', {
name : {type : String, default: ''},
services: [ServiceAddress]
});
module.exports = mongoose.model('ServiceAddress', {
serviceId : {type : ObjectId},
address: {type: String}
});
I'm trying to update an existing 'Env' document which has an empty array of 'services'.
router.put('/api/env', function(req, res, next) {
var env = new Environment(req.body);
env.save(function(err, updated){
if (err){
res.send(err);
}
res.json(updated);
});
});
The req.body content is:
{
_id: "56dd26a6618c1b983d5bada6",
name: "Test Drive"
services: [{_id: "56dc6e385fb0b038241d3399", address: "11"}, {_id: "56dc6e595fb0b038241d339a", address: ""}]
}
But the result in the DB is (only the IDs are pushed):
"services" : [ { "_id" : ObjectId("56dc6e385fb0b038241d3399") }, { "_id" : ObjectId("56dc6e595fb0b038241d339a") }
Any idea?
Thanks
Please try out with following snippet
var serviceSchema = {
serviceId : {type : ObjectId,required: false},
address: {type: String,required: false}
};
// added so that new _id field is not added when object is pushed in array
serviceSchema = 'new Schema('+serviceSchema +',{_id:false})';
module.exports = mongoose.model('Env', {
name : {type : String, default: ''},
services: [serviceSchema], default:[],
});
Thanks

Resources