Array of default values - mongodb

I have a schema looks like this
const userSchema = mongoose.Schema({
id: {
type: String,
},
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
notes: [
{
type: mongoose.Types.ObjectId,
ref: 'Note',
},
],
folders: [
{
type: String,
default: ['My notes', 'Todos', 'Projects', 'Journal', 'Reading list'],
},
],
});
here folder is an array, and I want to add some value by default when I create a user. But it doesn't work. It always returns an empty array. I want it to be like this by default,
folders: ['My notes', 'Todos', 'Projects', 'Journal', 'Reading list']
How can I achieve that?

Try this
folders: {
type: [String],
default: ['My notes', 'Todos', 'Projects', 'Journal', 'Reading list']
}

Related

How to generate auto increment count field using Mongodb Schema

I have a database related to the interview process which consists of multiple fields.
basically, there are 5 APIs
POST - (Candidate info) - for entering candidate data
PATCH - for updating candidate info
PATCH - (for Short Listing and reviewing) - updates in existing candidate
PATCH - (for Scheduling the candidate interview) - entering the interview field which is an array object.
GET Method
I want auto increment for the count field under Interview Round Count
whenever the PATCH Method is updated for the same candidate (data updated successfully)
How can I do that in Mongodb
Complete Schema:
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const { Schema } = mongoose;
const { EMAIL } = require('../../config/patterns.js');
const InterviewSchema = new Schema(
{
firstName: {
type: String,
required: true,
trim: true,
maxlength: 30,
},
lastName: {
type: String,
trim: true,
maxlength: 30,
},
email: {
type: String,
required: true,
trim: true,
match: EMAIL,
},
gender: {
type: String,
required: true,
enum: ['male', 'female', 'other'],
},
contactNumber: {
type: Number,
unique: true,
required: true,
},
alternateContactNumber: {
type: Number,
},
resume: {
type: String,
required: true,
},
designation: {
type: String,
required: true,
enum: ['trainee', 'se', 'sse', 'tl', 'systemEngineer'],
},
profile: {
type: String,
required: true,
enum: [
'react',
'reactNative',
'node',
'fullstack',
'php',
'ios',
'android',
'python',
],
},
experience: {
years: {
type: Number,
required: true,
},
months: {
type: Number,
required: true,
},
},
ctc: {
current: {
type: Number,
required: [true, 'In LPA'],
},
expected: {
type: Number,
required: [true, 'In LPA'],
},
offered: {
type: Number,
required: [true, 'In LPA'],
},
},
noticePeriod: {
type: Number,
default: 0,
},
referrer: {
type: {
type: String,
enum: ['consultant', 'employee', 'website', 'social'],
},
name: {
type: String,
trim: true,
required: true,
},
},
status: {
type: String,
enum: [
'shortlisting',
'shortlisted',
'interviewing',
'selected',
'rejected',
'onHold',
'denied',
'offerSent',
'joined',
'cancel',
],
},
// Shortling the Candidate - PATCH Method
reviewer: {
name: {
type: String,
trim: true,
required: true,
},
email: {
type: String,
trim: true,
required: true,
},
id: {
type: Number,
required: true,
},
},
date: {
type: Date,
default: Date.now,
},
// Scheduling the interview (this can be repeated no.of times for the interview round)
// represented in Array object
interview: [
{
interviewerName: {
type: String,
trim: true,
},
date: {
type: Date,
default: Date.now,
},
mode: {
type: String,
enum: ['telephonic', 'video', 'f2f'],
default: 'telephonic',
},
meeting: {
link: {
type: String,
trim: true,
},
platform: {
type: String,
trim: true,
},
},
round: {
count: { // want auto-increment count
type: Number,
},
type: {
type: String,
enum: ['written', 'technical', 'hr'],
},
},
interviewStatus: {
type: String,
enum: ['rejected', 'onHold', 'selected', 'schedule'],
},
feedback: {
technical: {
type: Number,
required: true,
min: 1,
max: 5,
},
logical: {
type: Number,
required: true,
min: 1,
max: 5,
},
communication: {
type: Number,
required: true,
min: 1,
max: 5,
},
comment: {
type: String,
min: 10,
max: 200,
},
},
recommendation: {
type: String,
enum: ['yes', 'no'],
},
},
],
},
{
timestamps: true,
},
);
InterviewSchema.plugin(mongoosePaginate);
const InterviewProcess = mongoose.model('interviewprocess', InterviewSchema);
module.exports = InterviewProcess;

how to use nested object as a ref in mongoose

I have two schemas user and note-
user schema
import mongoose from 'mongoose';
const userSchema = mongoose.Schema({
id: {
type: String,
},
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
notes: [
{
type: mongoose.Types.ObjectId,
ref: 'Note',
},
],
folders: {
type: [
{
name: {
type: String,
},
notes: [
{
type: mongoose.Types.ObjectId,
ref: 'Note',
},
],
},
],
default: [
{ name: 'My Notes', notes: [] },
{ name: 'Todos', notes: [] },
{ name: 'Projects', notes: [] },
{ name: 'Journals', notes: [] },
{ name: 'Reading list', notes: [] },
],
},
});
const User = mongoose.model('User', userSchema);
export default User;
note schema
import mongoose from 'mongoose';
const noteSchema = new mongoose.Schema({
id: {
type: String,
required: true,
},
modify_date: {
type: String,
required: true,
},
modify_time: {
type: String,
required: true,
},
tags: [
{
id: {
type: String,
required: true,
},
text: {
type: String,
required: true,
},
},
],
created_by: {
type: mongoose.Types.ObjectId,
ref: 'User',
required: true,
},
folder: {
type: String, //can I use ref from user?
},
title: {
type: String,
},
body: {
type: String,
required: true,
},
time_stamp: {
type: Date,
required: true,
},
});
const Note = mongoose.model('Note', noteSchema);
export default Note;
I have searched but could not find anything. I want to use the nested folder object from user schema as a ref in note schema; so, whenever I change or update a folders name all the notes get the updated value. Is it possible?
If not should I make a separate folder schema and add ref of folder schema in both note and user? How can I achieve that, any suggestion might be very helpful?

How to develop nested condition query in mongoDB

I am pretty new to mongoDb and want to apply nested query.
I have a business schema like this:
const businessSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
businessType: {
type: Schema.Types.ObjectId,
ref: "businessCategory",
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
review: {
type: [reviewSchema],
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
Business has a review where user can do the review and reviewSchema is
const reviewSchema = new mongoose.Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: "users",
required: true,
},
rating: {
type: Number,
enum: [1, 2, 3, 4, 5],
},
reviewArray: {
type: [singleReviewSchema],
},
},
{ timestamps: true }
);
One user can do many reviews, and it has reviewArray.
ReviewArray schema is
const singleReviewSchema = new mongoose.Schema(
{
title: {
type: String,
},
description: {
type: String,
},
isDeleted: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
How to fetch the business with a condition business: isDeleted:false and its reviews with singleReviewSchema: isDeleted:false
I dont know your model names, so please replace path with correct names
but it might look like:
businnesModel.find({isDeleted: false})
.populate({
path: 'reviewModelName',
model: 'review',
populate: {
path: 'reviewArray',
model: 'singleReviewModelName',
match: {
isDeleted : false
}
}
})
It should provide you array of businessModel documents - even when their singleReviews array will be empty (because all of reviews are deleted, or there was zero reviews). So you have to filter it out in JS.
To avoid filtering in JS, and to do it a bit more efficient way for mongodb, you can go with aggregate instead.

Mongoose error with PUT request but not with POST or GET

I have a schema that looks like:
const houseSchema = new mongoose.Schema({
address: {
type: String,
required: true,
trim: true,
},
city: {
type: String,
required: true,
},
roofType: {
type: String,
//required: true,
},
repairType: {
type: String,
//required: true,
},
numFloors: {
type: Number,
//required: true,
},
isOwner: {
type: Boolean,
//required: true,
},
isGated: {
type: Boolean
},
includeFlat: {
type: Boolean
},
addedBy: [
{
name:{
type: String
},
time:{
type: String
},
}
],
});
const customerSchema = new mongoose.Schema({
firstName: {
type: String,
required: true,
trim: true,
},
lastName: {
type: String,
required: true,
trim: true,
},
phoneNumber: {
type: String,
required: true,
},
email: {
type: String,
},
//array of houseSchema objects
properties: [
houseSchema
],
});
And my endpoint that is used to update one of the 'properties' is:
router.route('/property').post(async (req,res) => {
const body = req.body;
Customer.updateOne({_id: req.query.id, properties: {$elemMatch: {_id: req.query.pId}}},
{
$set: {
"properties.$.address": body.address,
"properties.$.city": body.city,
"properties.$.roofType": body.roofType,
"properties.$.repairType": body.repairType,
"properties.$.numFloors": body.numFloors,
"properties.$.isOwner": body.isOwner,
"properties.$.isGated": body.isGated,
"properties.$.includeFlat": body.includeFlat
}
},
function(err){
if(err){
res.status(400).json('Error: ' + err);
}
else{
res.json('Property Updated!');
}
}
)
});
The endpoint works mostly fine (it returns the customer and all properties when i only search for and want to modify one of the 'properties') but only when it is a post or a get request and when it is a put request, the error says
Error: ValidationError: firstName: Path firstName is required., lastName: Path lastName is required., phoneNumber: Path phoneNumber is required.
I dont know if its a big deal or not, but I do not know why this is happening and would like to know. Just to be clear, the goal of this endpoint is to find one of the properties and update its values, not to change anything about a customer or any of their other properties.

How to push an item to a nested array?

I am trying to make an api with express.js and mongoDB (using mongoose) and don't know how to properly add an item to my existing array (nextUp). For example I have an existing User in my database with templates: { issues: { nextUp: [], inProgress: [], completed: [] } } and want to add e.g. {issueName: 'MyName', issueDate: '20/5/2020'} to nextUp field.
const mongoose = require('mongoose');
const { Schema } = mongoose;
const UserSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
minlength: 3,
sparse: true,
},
email: {
type: String,
required: true,
unique: true,
minlength: 5,
maxlength: 255,
sparse: true,
},
password: {
type: String,
required: true,
minlength: 8,
sparse: true,
},
newsletterSubscribed: {
type: Boolean,
},
termsAndPolicyAgreement: {
type: Boolean,
required: true,
},
templates: {
title: {
type: String,
},
description: {
type: String,
},
issues: {
nextUp: [
{
issueName: {
type: String,
},
issueDate: {
type: String,
},
},
],
inProgress: [
{
issueName: {
type: String,
},
issueDate: {
type: String,
},
},
],
completed: [
{
issueName: {
type: String,
},
issueDate: {
type: String,
},
},
],
},
},
});
const UserModel = mongoose.model('user', UserSchema);
module.exports = UserModel;
I've tried to do that but my item hasn't added. (username Kacper exists there is no problem with that).
UserModel.findOneAndUpdate(
{ username: 'Kacper' },
{
$push: {
nextUp: [
{
issueName: 'MY NEW ISSUE',
issueDate: 'MY ISSUE DATE',
},
],
},
},
);