Update field in another schema with post hook mongoose - mongodb

I have that schemas:
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
module.exports = mongoose.model('OrderDetail', schema);
and
var schema = new Schema({
name: {type: String, required: true},
price: {type: Float, required: true},
idProvider: {type: Schema.Types.ObjectId, ref: 'Provider'},
idProduct: {type: Schema.Types.ObjectId, ref: 'Product'},
description: {type: String},
quantitySold: {type: Number}
});
module.exports = mongoose.model('ProdProv', schema);
I need to update field "quantitySold" when a post.save happens in order-detail, i've tried this:
schema.post('save', function(next){
//But this point I can't find the prodprov to update field
})
How I can do this?
Thank you.

Thank you #mjim, but that´s code not works. I've modify the code and works! this is my solution:
schema.post('save', function(doc){
var prod = ProdProv.findById(this.prodprov).exec().then((pp) => {
pp.quantitySold += this.quantity;
pp.save();
});
});

I would suggest:
var ProdProv = require('./ProdProv');
var schema = new Schema({
number: {type: Number},
subtotal: {type: Float, required: true},
quantity: {type: Number, required: true},
prodprov: {type: Schema.Types.ObjectId, ref: 'ProdProv'},
order: {type: Schema.Types.ObjectId, ref: 'Order'}
});
schema.post('save', async function(doc){
var prod = await ProdProv.findById(doc.prodprov);
prod.quantitySold = doc.quantity;
prod.save()
});
module.exports = mongoose.model('OrderDetail', schema);

Related

How to make an update on field depending on linked document field

I'm trying to conditionally update a field in a document but I need to know the value of an other field in a linked document. I'm struggling to explain my problem so i will give you my code and try to explain what I'm trying to do.
I got a route to update my 'workstation' collection
router.post("/workstation/update/:id", (req, res, next) => {
const id = req.params.id;
const previousWorkstation = req.body.previous;
const updatedWorkstation = req.body.updated;
const {errors, isValid} = validateWorkstation(updatedWorkstation);
if(!isValid){
return res.status(422).json(errors);
}
Workstation.findByIdAndUpdate(mongoose.Types.ObjectId(id), updatedWorkstation, (err, workstation) => {
if(err) return;
NonConformity.updateMany({workstation: previousWorkstation.name, line: previousWorkstation.line}, {$set:{workstation: updatedWorkstation.name}}, (err) => {
if(err) return;
Rework.updateMany({workstation: previousWorkstation.name}, {$set:{workstation: updatedWorkstation.name}}, (err) => {
if(err) return;
res.send(200);
})
})
})
});
My problem is I need to update rework depending on the line too, and not only the workstation name ! Here are my schemas
// WORKSTATION SCHEMA
const mongoose = require('mongoose');
const WorkstationSchema = mongoose.Schema({
name: {type:String, required: true},
line: {type:String, required: true}
})
const Workstation = mongoose.model('workstations', WorkstationSchema);
module.exports = Workstation;
// REWORK SCHEMA
const mongoose = require('mongoose');
const ReworkSchema = mongoose.Schema({
nonConformity_id: {type:String, required: true},
operator: {type:String, required: true},
fin: {type:String, required: true},
workstation: {type:String, required: false},
code: {type:String, required: true},
declination: {type:String, required: true},
description: {type:String, required: true},
advice: {type:String, required: false},
pps: {type: String, required: false},
quantity: {type:Number, required: true},
reworked: {type:Boolean, default: false, required: true},
verified: {type:Boolean, default: false, required: true},
})
const Rework = mongoose.model('nonConformities.reworks', ReworkSchema);
module.exports = Rework;
// NON CONFORMITY
const mongoose = require('mongoose');
const NonConformitySchema = mongoose.Schema({
number: {type: String, unique: true, required: true, dropDups: true},
line: {type: String, required: true},
product: {type: String, required: true},
workstation: {type: String, required: true},
msn: {type: String, required: true},
date: {type: String, required: true},
type: {type: String, required: true},
})
const NonConformity = mongoose.model('nonConformities', NonConformitySchema);
module.exports = NonConformity;
My question is : Is it possible to update my workstation name in the rework collection depending on the line name of the linked non conformity id in the rework schema ?
Sorry if my english is bad, i can try to reformulate if you don't understand my question.
Thanks in advance !

Mongoose Populate ignored for this basic setup

I have a User Schema, which has multiple notes, and the Note which belongs to a userId
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'Note'}]
});
const NoteSchema = new Schema({
userId: {type: mongoose.Types.ObjectId, ref: 'User'},
content: {type: String, required: true, trim: true, lowercase: true},
});
I'm trying to populate my User with the notes using the following syntax (from the docs)
const user = await User.findById(mongoose.Types.ObjectId("5bd2a8c4963ac00f57a18074"))
.populate('notes')
.exec(function (err, result) {
console.log(result);
});
But it's returning the User without the Notes data. Any idea what I might be doing wrong?
NoteSchema here is the problem:
userId: {type: mongoose.Types.ObjectId, ref: 'User'}
Use below,
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.Types.ObjectId, ref: 'User'}
// OR
userId: {type: Schema.ObjectId, ref: 'User'} // For backword compatibility
Note:- The schema should always use mongoose.Schema.Types. And mongoose.Types.ObjectId can be used withing mongoose implementation.
I am able to get document properly (Below code):
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
const NoteSchema = new Schema({
userId: {type: Schema.Types.ObjectId, ref: 'UserTest'},
content: {type: String, required: true, trim: true, lowercase: true},
});
const UserSchema = new Schema({
_id: Schema.Types.ObjectId,
email: {type: String, required: true, trim: true, lowercase: true, unique: true},
notes: [{type: Schema.Types.ObjectId, ref: 'NoteTest'}]
});
var Note = mongoose.model('NoteTest', NoteSchema);
var User = mongoose.model('UserTest', UserSchema);
User.find({_id : mongoose.Types.ObjectId("5bd2c84dd79cc5d8b1c62964")})
.populate('notes')
.exec(function (err, result) {
console.log("result.....", JSON.stringify(result));
});
Output:
[
{
"_id": "5bd2c84dd79cc5d8b1c62964",
"email": "hardik#com.com",
"notes": [
{
"_id": "5bd2c869d79cc5d8b1c62965",
"content": "ABC",
"userId": "5bd2c84dd79cc5d8b1c62964"
},
{
"_id": "5bd2c88ad79cc5d8b1c62966",
"content": "DEF",
"userId": "5bd2c84dd79cc5d8b1c62964"
}
]
}
]

Index containing multiple fields in MongoDB

In MongoDB, How do i restrict the data entry bases on 3 fields RegisterUserId ,PageId and IsFavourite. None of them is unique?
what should the query be?
Below is my Schema
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});
module.exports = mongoose.model('t_FavMaster', FavMasterSchema);
Try this:
var FavMasterSchema = new Schema({
FavUrl:String,
RegisterUserId : { type: Schema.Types.ObjectId, ref: 'User',select: false},
PageId: { type: Schema.Types.ObjectId},
IsFavourite: {type: Boolean,default:false}
});

Mongoose delete nested subdocuments and documents

I have:
let userSchema = mongoose.Schema({
email: {type: String, required: true, unique: true},
passwordHash: {type: String, required: true},
fullName: {type: String, required: true},
salt: {type: String, required: true},
ads: [{type: ObjectId, ref: 'Ad'}],
roles: [{type: String}]
}
let adSchema = mongoose.Schema({
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true},
category: {type: ObjectId, ref: 'Category', required: true},
town: {type: ObjectId, ref: 'Town', required: true},
}
);
let categorySchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
let townSchema = mongoose.Schema({
name: {type: String, required: true, unique: true},
ads: [{type: ObjectId, ref: 'Ad'}]
}
);
I want to find for example town by id and remove all ads in it(and ofcourse to remove the ads from their categories and authors).How can i do that?
I would suggest bulk getting the array of object Ids and using it like this:
Ad.remove({_id: {$in: Ad_ids_array}}, function(){...}); // and so on
You can add a pre-remove hook in the ad schema definition like this:
adSchema.pre('remove', function(next) {
let lethis = this;
// Pull ad out of all the Category docs that reference the removed ad.
this.model('Category').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
// Pull ad out of all the User docs that reference the removed ad.
this.model('User').update({}, { $pull: {ads: lethis._id}}, { safe: true }, next);
});
This will remove the ad from the categories and users that have it in their ads array.

How do I set a value to be fixed aka un-updateable

I'm making a database for beavers, however some properties should be unchangeable such as the birth date or the location where it was first seen.
How do I implement this? Is there a mongoose schema property for this? Or do I do it with JS?
Example of the schema:
let beaverSchema = new Schema({
id: {type: String, required: true, unique: true},
birthDate: {type: Date},
locationSpotted: {type: String},
firstSeen: {type: Date},
status: {type: String, default: "Alive"},
sex: {type: String}
})