MongoD: How to update specific field of a document in a collection? - node.js

I have a collection of jobs in MongoDB and in this collection there is a field in the documents named as appliedUser. I want to update this field when a new user applies for this job.So basically this field stores the id's of all the users who are applying for this job.
I am using findOneAndUpdate() function but not able to do it.
Job.findOneAndUpdate({ _id: req.params.id }, { $set: { appliedUser:
req.user.id } }, function(err, job) {
console.log(job);
})
and here is my Schema:
const jobSchema = new Schema({
date: { type: Date, default: Date() },
expirydate: { type: Date, required: true },
name: { type: String, required: true },
companydetails: { type: String, required: true },
address: { type: String, required: true },
role: { type: String, required: true },
city: { type: String, required: true },
minsalary: { type: Number, required: true },
maxsalary: { type: Number, required: true },
skills: { type: Array, required: true },
minex: { type: Number, required: true },
appliedUser: [{ type: Schema.Types.ObjectId, ref: 'users', unique:
true }],
user: { type: String, required: true }
})
The array of the document is not updating. I am not able to find the errors.

Look like what you need is $addToSet. Example:
Job.findOneAndUpdate({ _id: req.params.id }, { $addToSet: { appliedUser: req.user.id } }, function(err, job) {
console.log(job);
})

Related

How to get data from mongoDB on the basis of a value inside a nested object

Below is my API for fetching all the orders of a specific restaurant from a mongoDB database.
My search is based on the restaurant id which I am getting from params and passing it to the query object.
query1 is working but query2 does not return my data.
It is returning an empty array. If I pass a simple object in find() then I am getting a response. But when i use a nested object for getting data I get nothing.
exports.getOrders = async (req, res) => {
const restId = req.params.restId;
console.log("restaurant id", restId);
if (!restId) return res.status(404).send("No restaurant ID found in params");
const query1 = {grandTotal: 600};
const query2 = { restaurant: { restaurantId: restId } };
const response = await Orders.find(query2);
console.log("Printing response inside API function", response);
}
Below is my MongoDB Schema of Orders.
const mongoose = require("mongoose");
const orderSchema = mongoose.Schema({
customer: {
name: {
type: String,
required: true,
},
contact: {
type: String,
required: true,
},
customerId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Customer",
required: true,
},
customerAddress: {
type: String,
required: true,
},
},
restaurant: {
restaurantName: {
type: String,
required: true,
},
contact: {
type: String,
required: true,
},
restaurantId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Restaurant",
required: true,
},
},
/*date: {
day: {
type: Number,
required: true,
},
month: {
type: String,
required: true,
},
year: {
type: Number,
required: true,
},
},
type: {
type: String,
enum: ["delivery","takeaway"],
required: true,
},*/
items: [
{
itemId: { type: String, required: true },
itemName: { type: String, required: true },
itemDescription: { type: String, required: true },
price: {type: Number, required: true},
quantity: { type: Number, required: true },
total: {type: Number, required: true},
},
],
grandTotal: {type: Number, required: true},
status: {
type: String,
enum: ["pending", "rejected","cancelled","accepted","received"],
required: true,
},
});
orderSchema.virtual("booking", {
ref: "Booking",
localField: "_id",
foreignField: "orderId",
});
orderSchema.set("toObject", { virtual: true });
orderSchema.set("toJSON", { virtual: true });
const Orders = mongoose.model("Orders", orderSchema);
exports.Orders = Orders;
change query2 to this
const query2 = { "restaurant.restaurantId": restId } };

Mongoose/MongoDB Empty SubSchema Array

I have a model in Mongoose that looks like this:
const orderLogSchema = mongoose.Schema(
{
removed: { type: String, required: true },
},
{
timestamps: true,
}
)
const orderSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
orderItems: [
{
name: { type: String, required: true},
qty: { type: Number, required: true},
image: { type: String, required: true},
price: { type: Number, required: true},
product: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'Product'},
}
],
shippingAddress: {
address: { type: String, required: true },
city: { type: String, required: true },
postalCode: { type: String, required: true },
country: { type: String, required: true },
},
paymentMethod: {
type: String,
required: true,
},
paymentResult: {
id: { type: String },
status: { type: String },
update_time: { type: String },
email_address: { type: String },
},
taxPrice: {
type: Number,
required: true,
default: 0.0
},
shippingPrice: {
type: Number,
required: true,
default: 0.0
},
totalPrice: {
type: Number,
required: true,
default: 0.0
},
isPaid: {
type: Boolean,
required: true,
default: false
},
paidAt: {
type: Date,
},
isDelivered: {
type: Boolean,
required: true,
default: false
},
deliveredAt: {
type: Date,
},
couponCode: {
type: Object,
required: false
},
orderVerifyLog: [orderLogSchema],
}, {
timestamps: true
})
I need to be able to empty out the orderVerifyLog which is populated with the orderLogSchema. I have tried a bunch of things most recently I pulled the order into a variable, and I am able to access orderVerifyLog by using order.orderVerifyLog but I cant figure out how to empty out that orderLogSchema. I tried:
order.orderVerifyLog = []
order.save()
Is there an easy way to work with that "sub" schema and zero it out?
Basically I am pulling the log items from that schema for an order and displaying them on my front-end. Then I was to fire off an action to clears it out so they don't display every time the order is loaded (Only want them to show once). I also tired to loop over each item in the orderVerifyLog and use pull to remove them, but for some reason it always leaves one in there.

Mongoose: How to populate across multiple levels and use field selection in the same time?

I have succesfully used population across multiple levels and field selection separately. But I couldn't find a way to do them both at the same time.
Population across multiple levels
Profile.findOne({ user: req.user.id })
.populate({
path: "user",
populate: { path: "following" },
})
Field selection:
Profile.findOne({ user: req.user.id })
.populate("user", ["name", "avatar"])
I want to do something like this:
NOTE: THIS DOESN'T WORK
Profile.findOne({ user: req.user.id })
.populate({
path: ["user", ["name", "avatar"]],
populate: { path: "following" },
This is the Profile model:
const ProfileSchema = new Schema({
//We want to associate the user with the profile
user: {
//This will associate the user by his id
type: Schema.Types.ObjectId,
ref: "users",
},
// We want a user friendly url
handle: {
type: String,
// required: true, // Even though we are doing pre-validatioon
max: 40,
},
bio: {
type: String,
},
school: {
type: String,
},
major: {
type: String,
},
website: {
type: String,
},
location: {
type: String,
},
// Optional (might add it later)
/**
* status: {
//where they are in their career
type: String,
required: true
},
*/
skills: {
// In the form they will put skill1,skill2,.. and we will turn that into an array
type: [String],
// required: true,
},
interests: {
// In the form they will put interest1,interest2,.. and we will turn that into an array
type: [String],
// required: true,
},
help_offers: {
// In the form they will put help_offer1,help_offer2,.. and we will turn that into an array
type: [String],
// required: true,
},
// Might be volunteering experience
experience: [
{
title: { type: String, required: true },
company: {
type: String,
required: true,
},
location: {
type: String,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
// Not required, going to be a checkbox
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
education: [
{
school: { type: String, required: true },
degree: {
type: String,
required: true,
},
fieldofstudy: {
type: String,
required: true,
},
from: {
type: Date,
required: true,
},
to: {
type: Date,
// Not required, going to be a checkbox
},
current: {
type: Boolean,
default: false,
},
description: {
type: String,
},
},
],
social: {
youtube: {
type: String,
},
twitter: {
type: String,
},
facebook: {
type: String,
},
linkedin: {
type: String,
},
instagram: {
type: String,
},
},
date: {
type: Date,
dafault: Date.now,
},
videoURL: {
type: String,
},
});
This is the User model:
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
surname: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
avatar: {
type: String,
},
birthday: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
date: {
type: Date,
default: Date.now,
},
following: [
{
type: Schema.Types.ObjectId,
//The User has only ObjectId in uses array. ref helps us get full fields of User when we call populate() method.
//https://bezkoder.com/mongodb-many-to-many-mongoose/
ref: "users",
},
],
followers: [
{
type: Schema.Types.ObjectId,
ref: "users",
},
],
});
I am not sure if I understood your aim by this
Profile.findOne({ user: req.user.id })
.populate({
path: ["user", ["name", "avatar"]],
populate: { path: "following" },
But if what i understood is what you want, then we're lucky. here is what i got.
await RequestAproves.find()
.populate('user', 'firstName surname email roleId')
.populate({
path: 'request',
populate: [
{ path: 'budgetItem', select: 'code name' },
{ path: 'user', select: 'firstName surname' },
],
}
)
More details will come later, Sorry, I couldnt use your schema description, Incase it doesnt work out, let me know, ill try to use your schema.

Mongoose Populate Virtuals

How to populate array of objects not by _id? I need it because I use "market_hash_name" as id in my project and it's more effectively then use _id:
let schema = new mongoose.Schema({
steamid: {
type: String,
unique: true,
index: true,
required: true
},
inventory: [{
market_hash_name: String,
name: String,
assetid: {
type: String
},
instanceid: {
type: String,
default: '0'
},
contextid: {
type: String,
default: '2'
},
amount: {
type: Number,
default: 1
},
ongoing_price_manipulation: {
type: Boolean
},
price: {
type: Number
}
}]
});
I used virtuals but only for a separate model and it works:
schema.virtual('item_data', {
ref: 'Steamlytics',
localField: 'market_hash_name',
foreignField: 'market_hash_name'
});
this.find(query).populate("item_data").exec((err, items) => {});

Mongodb populate query in nodejs for having condition with populated field

bellow is my schema's for User, Task and Order. i want to have query which can give me all orders which is assign to particular User.
var User = mongoose.Schema({
firstName : {
type: String,
required: false
},
lastName : {
type: String,
required: false
},
password : {
type: String,
required: false
},
createdAt:{
type: Date,
require: false
},
role:{
type: String,
require: false
}
});
var Task = mongoose.Schema({
assignedOn : {
type:Date
},
assignedTo : {type:mongoose.Schema.Types.ObjectId, ref:'User'},
status : {
type:String
},
priority : {
type: String
},
completeBy:{
type: Date
}
});
var Order = mongoose.Schema({
orderDate:{
type: Date,
require: false
},
completionDate:{
type: Date,
require: false
},
status: {
type: String,
required: false
},
orderType: {
type: String,
required: false
},
remarks: {
type: String,
require: false
},
totalAmount: {
type: Number,
require: false
},
items: {
type: [],
require: true
},
billingAddress: {
type: IAddress,
require: true
},
shippingAddress: {
type: IAddress,
require: true
},
defaultTask: {type:mongoose.Schema.Types.ObjectId, ref:'Task'},
customer: {type:mongoose.Schema.Types.ObjectId, ref:'Customer'}
});
i am doing query like bellow which is not giving me proper result for specific user _id which i want , its giving me all Orders.
this._orderRepository.findAndPopulate({$match:{assignedTo:_id}},
{path:'defaultTask ', populate:{path:'items'}, populate:{path:'assignedTo' }}, function(err, result){
console.log("error =>"+err);
/*console.log("result=>"+result);*/
callback(err, result);
} )

Resources