I have a problem with mongoose. I use MEAN stack.
I have an House Schema with some fields. When I update the house (with save method) mongoose update all fields but set an array in nested object empty. Why?
HOUSE SCHEMA
const mongoose = require('mongoose');
const posSchema = require('./pos');
const reviewSchema = require('./reviews');
const roomSchema = require('./rooms');
const contactSchema = require('./contacts');
const nearSchema = require('./nears');
const houseSchema = new mongoose.Schema({
title: { type: String, required: true },
description: { type: String, required: true },
shared: {
description: { type: String, required: true },
photos: { type: [String], required: true }
},
// OTHER FIELDS
}, { timestamps: true });
mongoose.model('House', houseSchema);
UPDATE FUNCTION
House.findById(body.house._id, "-__v", async (err, house) => {
if (err) { return res.status(400).json(err); }
else if (!house) { return res.status(400); }
house.title = body.house.title;
house.totalSize = parseInt(body.house.totalSize.toString());
house.bathrooms = parseInt(body.house.bathrooms.toString());
house.totalBeds = parseInt(body.house.totalBeds.toString());
house.description = body.house.description;
house.totalFreeBeds = parseInt(body.house.totalFreeBeds.toString());
house.minPrice = parseFloat(body.house.minPrice.toString()).toFixed(2);
house.type = body.house.type;
house.level = body.house.level;
house.top_floor = body.house.top_floor;
house.rooms = body.house.rooms;
house.checkboxes = body.house.checkboxes;
house.contacts = body.house.contacts;
house.pos = body.house.pos;
house.save(err => {
if (err) { console.log(err); return res.status(400).json(err); }
return res.status(200).json({ status: 200, remove: remove });
});
});
Before updating house.shared.photos is ["foo", "bar"]
After is [].
Why?
You are not setting the house.shared anywhere.
Try adding house.shared = body.house.shared before save call.
Related
Our aim is to have a post hook in place where we can track changed fields.
Model file:
const VariationSchema = new Schema({
_id: {
type: String,
},
title: {
type: String,
},
desc: {
type: String,
},
});
VariationSchema.post('save', async function (doc) {
console.log(doc.modifiedPaths());
});
const VariationModel = mongoose.model('variation', VariationSchema);
module.exports = {
VariationModel,
VariationSchema,
};
Service file:
const variationDocument = await VariationModel.findById(variationId).select({});
variationDocument.desc = (Math.random() + 1).toString(36).substring(7);
await variationDocument.save();
return variationDocument.toJSON();
No matter what we do, doc.modifiedPaths() is always empty. Please help
I am using mongoose for database functionalities in my nodejs project.Below is my model.
Here is the POST request:
In MongoDb data is saving like this :
Here owers array is empty.
expense.js
const mongoose = require('mongoose');
const ExpenseSchema = new mongoose.Schema({
userid:{
type: String,
required: true
},
owers:[{
owerid:{
type: String
},
amt:{
type: Number
}
}],
name:{
type: String,
required: true
},
amount:{
type: Number,
require: true
}
});
const expense = mongoose.model('expense',ExpenseSchema);
module.exports = expense;
Whenever I am trying to insert something array is showing empty.Below is my code:
addExpense.js
const expense = require('../models/expense.js');
const addExpense = async (req,res) => {
const {name,amount,owerid,amt} = req.body;
console.log(name + " " + owerid);
const {userid} = req.params;
const expens = new expense({userid,name,amount});
try{
const data = await expens.save();
expens.owers.push({"owerid":owerid,"amt":amt});
res.send({"id":data._id});
}
catch(error){
res.send(error);
}
};
module.exports = {addExpense};
Someone let me know what I am doing wrong.
Try This
const {name,amount,owers} = req.body;
console.log(name + " " + owerid);
const {userid} = req.params;
const expens = new expense({userid,name,amount});
try{
const data = await expens.save();
//After you can push multiple data like that
JSON.parse(owers).map((value) => {
data.owers.push({
owerid: value.owerid,
amt: value.amt
})
})
data.save()
res.send({"id":data._id});
}
catch(error){
res.send(error);
}
I am very new to mongoose.
I am currently building a backend using Node.js, express.js, GraphQL, and mongoose.
I have a Drink schema and DrinkType Schema. I defined DrinkType schema as "alcohol", "juice", "tea". And I have added many drinks and each drink has DrinkType reference. Then, I would like to reference all the drinks from DrinkType.
This is the schema for drinkType
const drinkTypeSchema = new Schema({
name: {
type: String,
required: true,
},
createdDrinks: [
{
type: Schema.Types.ObjectId,
ref: 'Drink',
},
],
Here is the schema for drink
const drinkSchema = new Schema({
name: {
type: String,
required: true,
},
drinkType: {
type: Schema.Types.ObjectId,
ref: 'DrinkType',
},
})
This is the drink resolver. Whenever a new drink is created, I am pushing it to drinkType.
try {
const result = await drink.save()
createdDrink = transformDrink(result)
const drinkType = await DrinkType.findById(args.addDrinkInput.drinkTypeId)
if (!drinkType) {
throw new Error('DrinkType not found.')
}
drinkType.createdDrinks.push(drink)
await drinkType.save()
const drinkLoader = new DataLoader(drinkIds => {
return drinks(drinkIds)
})
const drinks = async drinkIds => {
try {
const drinks = await Drink.find({ _id: { $in: drinkIds } })
return drinks.map(drink => {
return transformDrink(drink)
})
} catch (err) {
throw err
}
}
const transformDrink = drink => {
return {
...drink._doc,
_id: drink.id,
drinkType: drinkType.bind(this, drink.drinkType),
}
}
const drinkType = async drinkTypeId => {
try {
const drinkType = await drinkTypeLoader.load(drinkTypeId.toString())
return {
...drinkType._doc,
_id: drinkType.id,
createdDrinks: () => drinkLoader.loadMany(drinkType._doc.createdDrinks),
}
I want this createdDrinks part to return the array of drink objects, but it is only returning the array of _ids.
I have been reading the mongoose documentation and it seems that using ObjectId is the correct way. Would you mind helping me out?
Thank you in advance.
I have an issue on my application (mongodb/nodejs), my aim is to save a collection :
const Job = require("../models/Job");
exports.saveJob = (req, res, next) => {
const newJob = new Job(req.body);
newJob.gender = 'Male';
newJob.save((err, myjob) => {
myjob.code = '1234';
myjob.save((err, mysavedjob) => {
console.log(mysavedjob);
/** OUTPUT **
* { __v: 0,
updatedAt: 2018-07-31T08:31:47.664Z,
createdAt: 2018-07-31T08:31:47.664Z,
gender:'Male',
code:'1234',
...
}
*/
})
})
}
As you can see, the code output the saved document, but when I check the database , I don't have the code:'1234' I have just
{ __v: 0,
updatedAt: 2018-07-31T08:31:47.664Z,
createdAt: 2018-07-31T08:31:47.664Z,
gender:'Male',
...
}
==== UPDATE (adding the JobModel) ====
const mongoose = require("mongoose");
const JobSchema = new mongoose.Schema(
{
userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
code: String,
gender: String,
},
{ timestamps: true }
);
module.exports = mongoose.model("Job", JobSchema, "jobs");
Someone could tell me why please ?
thank you.
I am not sure this is the correct way to alter a job after saving it but try this
const Job = require("../models/Job");
exports.saveJob = (req, res, next) => {
const newJob = new Job(req.body);
newJob.gender = 'Male';
newJob.save((err, myjob) => {
myjob.code = '1234';
Job.findOneAndUpdate({_id: myjob._id}, myjob, (err, mysavedjob) => {
console.log(mysavedjob);
});
})
}
I followed this mongoose documentation on custom schema type, to create a "large string":
"use strict";
const mongoose = require('mongoose')
let STRING_LARGE = (key, options) => {
mongoose.SchemaType.call(this, key, options, 'STRING_LARGE');
};
STRING_LARGE.prototype = Object.create(mongoose.SchemaType.prototype);
STRING_LARGE.prototype.cast = function(val) {
let _val = String(val);
if(!/^[a-zA-Z0-9]{0,400}$/.test(_val)){
throw new Error('STRING_LARGE: ' + val + ' is not a valid STRING_LARGE');
}
return _val; };
module.exports = STRING_LARGE;
And I use it like this in a schema:
"use strict";
const mongoose = require('mongoose');
mongoose.Schema.Types.STRING_LARGE = require('./types/string_large')
const schema = new mongoose.Schema({
details: { type: STRING_LARGE, required: true },
link: { type: STRING_LARGE, required: true }
});
module.exports = schema;
But I get the error :
[path]\schemas[shema.js]:8
details: { type: STRING_LARGE, required: true },
ReferenceError: STRING_LARGE is not defined
at Object. ([path]\schemas[shema.js]:8:24)
...
-------------------------- UPDATE : WORKING CODE --------------------------
use "function ()" instead of "() =>"
"use strict";
const mongoose = require('mongoose')
function STRING_LARGE (key, options) {
mongoose.SchemaType.call(this, key, options, 'STRING_LARGE');
};
STRING_LARGE.prototype = Object.create(mongoose.SchemaType.prototype);
STRING_LARGE.prototype.cast = function(val) {
let _val = String(val);
if(!/^[a-zA-Z0-9]{0,400}$/.test(_val)){
throw new Error('STRING_LARGE: ' + val + ' is not a valid STRING_LARGE');
}
return _val; };
use "mongoose.Schema.Types.LARGE_STRING" instead of "LARGE_STRING"
module.exports = STRING_LARGE;
"use strict";
const mongoose = require('mongoose');
mongoose.Schema.Types.STRING_LARGE = require('./types/string_large')
const schema = new mongoose.Schema({
details: { type: mongoose.Schema.Types.STRING_LARGE, required: true },
link: { type: mongoose.Schema.Types.STRING_LARGE, required: true }
});
module.exports = schema;
You are assigning your type to mongoose.Schema.Types.STRING_LARGE and then use STRING_LARGE - that's where your ReferenceError is thrown. You have to use your type directly:
const schema = new mongoose.Schema({
details: { type: mongoose.Schema.Types.STRING_LARGE, required: true },
link: { type: mongoose.Schema.Types.STRING_LARGE, required: true }
});