Would like to .push fields of an embedded structure into an embedded model document on a .push method.
http://mongoosejs.com/docs/2.7.x/docs/embedded-documents.html
The console errors this though: SyntaxError: Unexpected token .
..for pushing bar.this : req.body.this, when concatenating for the embed in the embedded model
The models look like this:
var OneModel = new Schema({
foo: String,
bar: {
this : String,
that : Number,
}
});
var TwoModel = new Schema({
foo: String,
bar: {
this : String,
that : Number,
},
modelone: [OneModel]
});
And the NodeJS API looks this:
var ModelsOneTwo = require('./app/models/modelsonetwo');
router.route('/modeltwo/:modeltwo_id')
// update TwoModel with this _id
//(accessed at PUT http://localhost:4200/api/v1/modeltwo/:modeltwo_id)
.put(function(req, res) {
ModelsOneTwo.findById(req.params._id, function(err, modeltwo) {
if (err)
res.send(err);
// embedded document updating
// http://mongoosejs.com/docs/2.7.x/docs/embedded-documents.html
modeltwo.modelone.push({
foo : req.body.foo,
bar.this : req.body.this,
bar.that : req.body.that
});
// save the modeltwo, and check for errors
modeltwo.save(function(err) {
if (err)
res.send(err);
res.json({ message: req.params.modeltwo_id + ' ' + req.body.foo });
});
});
});
To set the properties of bar in the model, you'll have to create the additional Object for it:
modeltwo.modelone.push({
foo : req.body.foo,
bar : {
this : req.body.this,
that : req.body.that
}
});
This is similar to how it was defined in the schema:
var OneModel = new Schema({
foo: String,
bar: {
this : String,
that : Number,
}
});
Related
Within this post function i am trying to award a badge and then after the badge has been awarded within an array to the usermodel i am trying to update a separate field in the user doc which i have named as points, the udoc.total points currently works however after the call is finished the users total points do not update and stay as 0
Usermodel schema -
var schema = new Schema({
email : {type:String, require:true},
username: {type:String, require:true},
password:{type:String, require:true},
creation_dt:{type:Date, require:true},
diabeticType:{type:String, require:true},
badges: [Badges],
totalPoints: {type:Number, require:true},
glucoseReading : [
{
bloodGlucoseLevel : {
type : String,
required : "Required"
},
dosageTime : {
type : String,
},
unitsOfInsulinForFood : {
type : String,
},
correctionDose : {
type : String,
},
creation_dt :{
type : String,
}
}
]
});
and then this is the post command where the badge is added to the users profile however the total points do not update
router.post("/:id/badge/:bid", function (req, res){{'useFindAndModify', false}
Badgemodel.findById(req.params.bid).then(doc => {
if(!doc)
{
return res.status(404).end();
}
else
{
var awardBadge = doc;
Usermodel.findByIdAndUpdate(req.params.id,
{$push : {badges : awardBadge}},
{safe : true, upsert: true}).then(udoc =>{
if(!doc)
{
return res.status(404).end();
}
else
{
console.log(udoc);
console.log(udoc.totalPoints);
udoc.totalPoints = udoc.totalPoints + awardBadge.value;
console.log(udoc.totalPoints);
return res.status(200).end();
}
})
}
})
})
I think you have an error in your User Schema.
You are trying to reference a array of documents of the Badges collection in your User Schema definition at badges: [Badges],.
But when you reference a doc from an other collection in mongoose the syntax is different.
Checkout the mongoose docs.
The schema should look like this:
badges: [{
type: Schema.Types.ObjectId,
ref: "UserModel" // or whatever the Model name is
}]
see also
https://mongoosejs.com/docs/api/schematype.html#schematype_SchemaType-ref
Answer- I was storing the value for total points into a variable and this variable was not being sent back to the users info. I updated code by adding in another findbyidandupdate and included the $set function to update the users total points to the value of the variable udoc.total points.
router.post("/:id/badge/:bid", function (req, res){{'useFindAndModify', false}
Badgemodel.findById(req.params.bid).then(doc => {
if(!doc)
{
return res.status(404).end();
}
else
{
var awardBadge = doc;
Usermodel.findByIdAndUpdate(req.params.id,
{$push : {badges : awardBadge}},
{safe : true, upsert: true}).then(udoc =>{
if(!doc)
{
return res.status(404).end();
}
else
{
console.log(udoc);
console.log(udoc.totalPoints);
udoc.totalPoints = udoc.totalPoints + awardBadge.value;
Usermodel.findByIdAndUpdate({_id: req.params.id}, {$set: {totalPoints : udoc.totalPoints} }).then(doc => {
if(!doc)
{
return res.status(404).end();
}
else
{
return res.status(200).end();
res.send(doc);
}
})
console.log(udoc.totalPoints);
return res.status(200).end();
res.send(doc);
}
})
}
})
})
I thought I could read my way to this solution, but I cant see what im doing wrong.
Here is my model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var inspectSchema = new Schema({
_id: Object, // Mongo ID
property: String, // Property ID
room: String, // The room Name
item: Array // The Items text
});
module.exports = mongoose.model('inspectModel', inspectSchema, 'inspect');
And here is where I try to insert or insertOne
var inspectModel = require('../../models/inspectModel');
var inspectTable = mongoose.model('inspectModel');
inspectTable.insert(
{
"property" : inspectRecord.property,
"room" : inspectRecord.room,
"item" : inspectRecord.item
},
function (err, res) {
if (err) { return reject({err:true, err:"addInspect ERROR" + err}) }
else {
show("=====RESOLVE addInspect=====")
return resolve();
}
})
I tried
inspectTable.insert
inspectModel.insert
inspectTable.insertOne
inspectModel.insertOne
No matter what I always get
TypeError: inspectTable.insert is not a function
I also tried just update with { upsert: true } but then the mongo ID becomes null.
Any ideas?
The method you're looking for is create:
inspectTable.create(
{
"property" : inspectRecord.property,
"room" : inspectRecord.room,
"item" : inspectRecord.item
}, ...
However, your schema definition of _id: Object is likely wrong. Just leave any definition of _id out of your schema and it will use the default ObjectId, which is likely what you want.
You can try this
var insert_table = new inspectTable(
{
"property" : inspectRecord.property,
"room" : inspectRecord.room,
"item" : inspectRecord.item
});
insert_table.save(function (err, res) {
if (err) { return reject({err:true, err:"addInspect ERROR" + err}) }
else {
show("=====RESOLVE addInspect=====")
return resolve();
}
});
I'm new to Mongoose and Nodejs developement in general and I've got a bit of confusion around how to properly set up saving my records. Here are my two schemas:
Download
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var downloadSchema = Schema({
title : String,
description : String,
_project : { type: Schema.Types.ObjectId, ref: 'Project' }
});
module.exports = mongoose.model('Download', downloadSchema);
Project
...
var projectSchema = Schema({
name : String,
url : String,
pwd : String,
_downloads : [{type: Schema.Types.ObjectId, ref: 'Download' }]
});
module.exports = mongoose.model('Project', projectSchema);
This appears to be working correctly. The documentation explains my use-case of saving a download and linking a project, but I'm not sure how to properly populate the Project._downloads. Here's what I've done:
Express route handler:
function createDownload(req, res) {
// the Project Id is passed in the req.body as ._project
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
var dload = new Download(dldata);
dload.save( function (err, download) {
project._downloads.push(download._id);
project.save( function(err){
var msg = {};
if(err) {
msg.status = 'error';
msg.text = err;
}else {
msg.status = 'success';
msg.text = 'Download created successfully!';
}
res.json(msg);
});
});
});
}
This seems overcomplicated to me. Am I supposed to be manually pushing to the ._downloads array, or is that something Mongoose is supposed to handle internally based on the schema? Is there a better way to achieve it so that I can do:
Download.find().populate('_project').exec( ...
as well as:
Project.findOne({_id : _projectId}).populate('_downloads').exec( ...
According to the mongoose docs there are 2 ways to add subdocs to the parent object:
1) by using the push() method
2) by using the create() method
So I think that your code can be a bit simplified by eliminating the operation of saving a new Download item:
function createDownload(req, res) {
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
// handle error
project._downloads.push(dldata);
project.save(function(err) {
// handle the result
});
});
}
or
function createDownload(req, res) {
var dldata = req.body;
Project.findOne({ _id : dldata._project }, function(err, project) {
// handle error
project._downloads.create(dldata);
project.save(function(err) {
// handle the result
});
});
}
I'm working on an application in Node with Mongoose where you're able to post blog entries and tag them. When a blog entry is deleted, I want to remove it's reference from the blog, and here's where I need help.
Below is the route for deleting a blog entry, but I get "TypeError: Cannot call method 'find' of undefined" when I try to delete a blog entry, so I guess my code below is wrong.
app.post('/blog/delete/:id', function(req, res){
model.BlogPost.findById(req.params.id, function (err, blog){
if (err) {
console.log(err);
// do something
}
blog.remove(function(err) {
console.log(err);
// do something
});
var query = model.Tag.find( { blogs: { $in : blog } } );
query.exec(function (err, tags) {
if (err) {
console.log(err);
// do something
}
tags.remove();
res.redirect('back');
});
});
});
Model for blog entries:
var BlogPostSchema = new Schema({
name : String,
type : String,
author : ObjectId,
title : String,
body : String,
buf : Buffer,
date: { type: Date, default: Date.now },
comments : [CommentSchema],
meta : {
upvotes : Number,
downvotes : Number,
// points : { type Number, default: },
favs : Number,
uniqueIPs : [String],
tags : [String]
}
});
modelObject.BlogPost = mongoose.model('BlogPost', BlogPostSchema);
Model for tags:
var TagSchema = new Schema({
name : String
, blogs : [String]
});
modelObject.TagSchema = TagSchema;
modelObject.Tag = mongoose.model('Tag', TagSchema);
Hard to tell with out line numbers, but looks like model.Tag may be undefined.
side note: you probably don't want to remove the tags unless the blog was found and removed successfully.
I'm trying to add an embedded document to an existing document field. I found one fitting answer with the search but I'm running into errors. I'm using node.js, Express and Mongoose.
My database schemas:
var entry = new Schema({
name : { type : String, required : true},
description : { type : String, default: ""},
});
var compo = new Schema({
name : String,
description : String,
entries : [entry]
});
And I'm trying to update the entries array with the following code
var entry = new entryModel();
entry.name = "new name";
entry.description= "new description";
compoModel.findOne(query, function (err, item) {
if (item) {
item.entries.push(entry);
item.save(function (err) {
if (!err) {
log.debug('Entry added successfully.');
} else {
log.error("Mongoose couldn't save entry: " + err);
}
});
}
});
It yields an error: TypeError: Object.keys called on non-object
What have I missed?
So I managed to get it working via the Model.update method by simply adding a new object to the compo.entries list and calling compoModel.update.
My similar issue (same error) was solved by clearing the sub-document array. It was populated prior to the definition of the sub-document scheme. At least this is what i think happened.
E.g.:
var token = new Schema( { value: String, expires: Date } )
var user = new Schema( { username: String, tokens: [token] } )
.. and, prior to defining the 'token' scheme i had entries such as:
{ username: 'foo', tokens: ['123456'] }
.. so, clearing tokens did it for me.
user.tokens = []
user.save()