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 !
Related
I'm trying to save a new use in mongodb with mongoose, but I am getting ValidationError: "err": "User validation failed:Path 'email' is required., Path 'fname' is required., Path 'username' is required phone: Path phone .despite I make all the data in the body of the post request so:
this is the userModel:
import mongoose from "mongoose";
const userSchema = new mongoose.Schema({
_id: {type: Number},
name: {type: String, required: true},
fname: {type: String, required: true},
phone: {type: String, required: true},
email: {type: String, required: true, unique: true},
password: {type: String, required: false},
image: {type: String, required: false},
isAdmin: {type: Boolean, default: false, required: true},
}, {
timeStamps: true
});
const User = mongoose.model('User', userSchema);
export default User;
this is the userRouter.js:
import express from "express";
import data from '../../data.js';
import User from "../userModel.js";
import expressAsyncHandler from "express-async-handler";
import {generateToken} from "../../utils.js";
import bcrypt from "bcryptjs";
const userRouter = express.Router();
let allUsers = data.users;
userRouter.get("/seed", expressAsyncHandler(async(req, res)=>{
//await User.remove({});
const createdUsers = await User.insertMany(allUsers);
res.send({createdUsers});
}));
userRouter.post("/register", expressAsyncHandler(async(req, res)=> {
//await User.remove({});
const user = new User({
name: req.body.name,
fname: req.body.fname,
phone: req.body.phone,
email: req.body.email,
});
const createdUser = await user.save();
res.send({
_id: createdUser._id,
name: createdUser.name,
fname: createdUser.fname,
phone: createdUser.phone,
email: createdUser.email,
token: generateToken(createdUser)
})
}))
export default userRouter;
I want to populate the details of products in my order. Currently it is only adding product id inside the products array. I tried a couple of methods but none seems to work.
import mongoose from 'mongoose'
const CartItemSchema = new mongoose.Schema({
product: {type: mongoose.Schema.ObjectId, ref: 'Product'},
quantity: Number,
shop: {type: mongoose.Schema.ObjectId, ref: 'Shop'},
status: {type: String,
default: 'Not processed',
enum: ['Not processed' , 'Processing', 'Shipped', 'Delivered', 'Cancelled']}
})
const CartItem = mongoose.model('CartItem', CartItemSchema)
const OrderSchema = new mongoose.Schema({
products: [CartItemSchema],
customer_name: {
type: String,
trim: true,
required: 'Name is required'
},
customer_email: {
type: String,
trim: true,
match: [/.+\#.+\..+/, 'Please fill a valid email address'],
required: 'Email is required'
},
delivery_address: {
street: {type: String, required: 'Street is required'},
city: {type: String, required: 'City is required'},
state: {type: String},
zipcode: {type: String, required: 'Zip Code is required'},
country: {type: String, required: 'Country is required'}
},
payment_id: {},
updated: Date,
created: {
type: Date,
default: Date.now
},
user: {type: mongoose.Schema.ObjectId, ref: 'User'}
})
const Order = mongoose.model('Order', OrderSchema)
export {Order, CartItem}
I tried doing this:
const create = async (req, res) => {
try {
req.body.order.user = req.profile;
console.log(req);
let order = new Order(req.body.order);
let neworder = await Order.findById(order._id)
.populate("products.product", "name price")
.populate("products.shop", "name")
.exec();
// console.log(order);
let result = await order.save();
sendMail(order);
res.status(200).json(result);
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err),
});
}
};
Also tried using this for poulating the product details but doesnt seem to work!
Order.findById(order._id).populate({ path: "products.product", select: "_id name price" })
Below is the schema. i want to get the answers as per matched qid, but i am getting all the answers in the answers array. i have tried almost all the queries but not able to understand why is this happening, if you could give link to other article that will be helpful too.
const id = req.params.id;
Channel.findOne({answer: {qid: {$in: [id]}}})
.then(result => {
console.log(result);
// let userAnswer;
// userAnswer = result.answer.map(i => {
// return {userId: i.userId , userName: i.userId.name, answer: i.answer}
// });
// res.json({ans: userAnswer, question: result.content});
})
.catch(err => {
console.log(err);
});
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const channelSchema = new Schema({
name: {
type: String,
required: true
},
category: {
type: String,
required: true
},
creator: {
type: String,
required: true
},
subscribers: [{type: mongoose.Types.ObjectId, required: true, ref: 'User'}],
content: {
question: [{
title: {type: String, required: true},
userId: {type: mongoose.Types.ObjectId, required: true, ref: 'User'}
}]
},
answer: [{
answer: {type: String, required: true},
qid: {type: mongoose.Types.ObjectId, required: true},
userId: {type: mongoose.Types.ObjectId, required: true, ref: 'User'}
}]
});
const model = mongoose.model('Channel', channelSchema);
module.exports = model;
const id = req.params.id;
return Channel.findOne({answer: {qid: {$in: [id]}}})
.then(snapshot => {
const results = [];
snapshot.forEach(doc => {
results.push({
id: doc.id,
data: doc.data()
});
});
return results;
})
})
.catch(err => {
console.log(err);
});
This is the way when you are going to fetch one array record. Not tested, only to show you how to get single record from collection
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"
}
]
}
]
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.