how to use nested object as a ref in mongoose - mongodb

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?

Related

Re: Correct MongoDb Relationships

Hi clever MongoDB people,
I am extremely new to Mongo DB and am trying to teach myself coding but I am battling with the practical side of collections.
I am attempting to create an employee management system and would like to know how do I get the different schemas/collections to only deal with the individual User’s employees.
A user will register using this schema;
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
lowercase: true,
},
companyName: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
role: {
type: String,
default: "customer",
},
CreatedAt: {
type: Date,
default: () => Date.now(),
},
UpdatedAt: {
type: Date,
default: () => Date.now(),
},
});
const User = mongoose.model("User", UserSchema:
);
module.exports = User;
Then the system takes them to a Profile page where they create a profile;
Profile Schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ProfileSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
required: true,
},
contactPerson: {
type: String,
required: true,
},
companyName: {
type: String,
required: true,
},
mobileNo: {
type: String,
required: true,
},
workNo: {
type: String,
},
email: {
type: String,
required: true,
},
industry: {
type: String,
},
CreatedAt: {
type: Date,
default: () => Date.now(),
},
UpdatedAt: {
type: Date,
default: () => Date.now(),
},
});
const Profile = mongoose.model("Profile", ProfileSchema);
module.exports = Profile;
Then they can add their employees.
Employee Schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const EmployeeSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
required: true,
},
employeeNo: {
type: String,
},
title: {
type: String,
},
employeeName: {
type: String,
required: true,
},
surname: {
type: String,
required: true,
},
gender: {
type: String,
},
race: {
type: String,
},
passportNo: {
type: String,
},
IDnumber: {
type: Number,
},
DOB: {
type: Date,
},
aka: {
type: String,
},
midName: {
type: String,
},
marriage: {
type: String,
},
passportExpires: {
type: Date,
},
mobileNo: {
type: String,
},
empEmail: {
type: String,
lowercase: true,
},
CreatedAt: {
type: Date,
default: () => Date.now(),
},
UpdatedAt: {
type: Date,
default: () => Date.now(),
},
});
const Employee = mongoose.model("Employee", EmployeeSchema);
module.exports = Employee;
Once an employee has been created there are various schemas connected with the employee, such as Personal contact details schema, Job details schema, Emergency contact details schema and so on.
This is my Emergency contact details schema:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const EmergencySchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
required: true,
},
emergContactPerson: {
type: String,
required: true,
},
emergWorkNo: {
type: String,
},
emergMobileNo1: {
type: String,
required: true,
},
emergMobileNo2: {
type: String,
},
medicAidName: {
type: String,
},
medicPlan: {
type: String,
},
medicMemberNo: {
type: String,
},
medicDepCode: {
type: Number,
},
CreatedAt: {
type: Date,
default: () => Date.now(),
},
UpdatedAt: {
type: Date,
default: () => Date.now(),
},
});
const Emergency = mongoose.model("Emergency", EmergencySchema);
module.exports = Emergency;
My question is How do I create a one-to-many relationship between my schemas so that each User will only see their employees and their personal details?
Please can you help me?

Array of default values

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']
}

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.

find one with multiple conditions mongoose mongodb

I am trying to obtain data from mongodb. This is the scenario. Each user has a following property(array) that takes an array of users id.
The user model is as below
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
followers: [{ type: mongoose.Types.ObjectId, ref: "user" }],
following: [{ type: mongoose.Types.ObjectId, ref: "user" }],
});
in simple terms. I need to use two conditions where postedBy: { $in: req.user.following }, or postedBy:req.user._id
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
body: {
type: String,
required: true,
},
photo: {
type: String,
required: true,
},
likes: [{ type: mongoose.Schema.ObjectId, ref: "user" }],
comments: [
{
text: String,
postedBy: { type: mongoose.Schema.Types.ObjectId, ref: "user" },
},
],
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
},
});
I have not figured out the second condition to add in the code below.
router.get("/getSubPost", requireLogin, async (req, res) => {
try {
const result = await Post.find({
postedBy: { $in: req.user.following },
})
.populate("postedBy", "-password")
.populate("comments.postedBy", "_id name");
res.json({ result });
} catch (error) {
console.log(error);
}
});

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',
},
],
},
},
);