Mongoose many to many relationship with additional data - node.js

Product Schema:
var ProductSchema = new Schema({
productName: {type: String, required: true},
});
Client schema:
var ClientSchema = new Schema({
clientName: {type: String, required: true},
products: [{ type : mongoose.Schema.ObjectId, ref : 'Product'}],
});
How can I add additional fields to the relationship? For example add field quantity:
var ClientSchema = new Schema({
clientName: {type: String, required: true},
products: [{ type : mongoose.Schema.ObjectId, ref : 'Product', quantity: Number}],
});

Related

Translate mongo nested array query into mongoose

I have the following query working with mongo, it returns the expected result
db.getCollection('trainings').find({"sections.employees.employee":ObjectId("5d3afa1a58a7160ea451d1db")})
but when I try the following call with mongoose, it returns an empty array
Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Need some helping to translate the mongo query to mongoose.
If you need anything else just add a comment and I will post here.
It's worth mentioning that I have already tried passing a new ObjectId with the String value, but it also returns an empty array.
Edit: Query usage
return await Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Edit: Model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const EmployeeSection = new Schema({
employee: {type: Schema.Types.ObjectId, ref: 'Employee', required: true},
fulfilled: {type: Boolean, default: null},
});
const Section = new Schema({
order: {type: Number, required: true},
date: {type: Date},
employees: {type: [EmployeeSection]},
answers: {type: Number},
hits: {type: Number}
});
const GoalSchema = new Schema({
understanding: {type: Number, required: true},
fixation: {type: Number, required: true}
});
const Evidence = new Schema({
description: {type: String, required: true},
file: {type: String}
});
const Question = new Schema({
participants: {type: Number},
answers: {type: Number},
hits: {type: Number}
});
const TrainingSchema = new Schema({
company: {type: Schema.Types.ObjectId, ref: 'Company', required: true, index: true},
creationDate: { type: Date, default: Date.now },
title: {type: String},
obs: {type: String},
questionNumber: {type: Number},
reference: {type: String},
sections: {type: [Section]},
goals: {
answers: {type: GoalSchema, required: true},
hits: {type: GoalSchema, required: true}
},
evidences: {type: [Evidence]},
questions: {type: [Question]},
area: {type: Schema.Types.ObjectId, ref: 'TrainingArea', required: true},
});
const Training = mongoose.model('Training', TrainingSchema);
module.exports = Training;
I am willing to change the Model schema, if the problem really lays there, but didn't really want to do it.
Why its always a typo?
db.getCollection('trainings').find({"sections.employees.employee":ObjectId("5d3afa1a58a7160ea451d1db")})
Training.find({'section.employees.employee': "5d3afa1a58a7160ea451d1db"})
Forgot s on sections
Made the problem a bit easier for me.
const mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/training", { useNewUrlParser: true })
const util = require("util")
const Schema = mongoose.Schema;
const EmployeeSection = new Schema({
employee: {type: Schema.Types.ObjectId, ref: 'Employee', required: true}
});
const Section = new Schema({
employees: {type: [EmployeeSection]}
});
const TrainingSchema = new Schema({
sections: {type: [Section]}
});
const Training = mongoose.model('Training', TrainingSchema);
Training.find(
{
"sections.employees.employee": mongoose.Types.ObjectId("5d3afa1a58a7160ea451d1db")
})
.exec()
.then(result => {
console.log(util.inspect(result, false, null, true /* enable colors */))
}).catch(err =>{
console.log(err)
})

How do I use nested schemas in mongoose, using 'type', to create arrays?

I am trying to create a nested mongoose schema that uses 'type' to create a nested array.
The schema that I think I am having an issue with is "chorePerson".
Here is the data that I am trying to put into a schema:
{
"chart": [
{
"ordinal": 0,
"chorePerson": [
{
"person": "emily",
"chore": "Catbox"
},
{
"person": "Steve",
"chore": "Dishes"
}
]
}
]
Here is my current schema. Note the use of "type" for "chart" and "chorePerson"
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chorePersonSchema = new mongoose.Schema({
person: {type: String, requried: true},
chore: {type: String, required: true},
});
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson:{ type: chorePersonSchema },
});
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
currentWeekNumber: {type: Number, required: true},
currentYear: {type: Number, required: true},
chart:{ type: chartSchema },
date: {type: Date, default: Date.now},
})
module.exports = ChoreChart = mongoose.model('cm_chorechart', ChoreChartSchema)
When I run my code this is what I get before the crash:
{ _id: 5c742ed116a095522c38ddfc,
affiliation: 'family',
currentYear: 2019,
currentWeekNumber: 9,
date: 2019-02-25T20:26:33.914Z,
chart: [ { ordinal: 0, chorePerson: [Array] } ] }
I think... chorePerson is causing the error... but I don't know how to fix it.
Here is the exception:
(node:6728) UnhandledPromiseRejectionWarning: ObjectExpectedError: Tried to set nested object field `chart` to primitive value `[object Object]` and strict mode is set to throw.
What I have tried
I tried this schema:
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson : [{
person : String,
chore : String
}]
});
Update:
OK... so I went back to basics and this works, but it's not how I want the final schema to be. Can anybody help out with nesting this ?
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
currentWeekNumber: {type: Number, required: true},
currentYear: {type: Number, required: true},
// chart:{ type: chartSchema },
chart:[{
ordinal: 0,
chorePerson : [{
person : String,
chore : String
}]
}],
date: {type: Date, default: Date.now},
})
Turns out it was easier than I thought:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const chorePersonSchema = new mongoose.Schema({
person: {type: String, requried: true},
personID: {type: String, required: true},
chore: {type: String, required: true},
choreID: {type: String, required: true},
});
const chartSchema = new mongoose.Schema({
ordinal: {type: Number, required: true},
chorePerson : [{ type:chorePersonSchema }]
});
// create the schema
const ChoreChartSchema = new Schema({
affiliation: {type: String, required: true},
weekNumber: {type: Number, required: true},
year: {type: Number, required: true},
chart:[{type: chartSchema}],
date: {type: Date, default: Date.now},
})
module.exports = ChoreChart = mongoose.model('cm_chorechart', ChoreChartSchema)

reddit comment system how to replicate in mongodb/nodejs

How do I make nested comment replies in MongoDB/mongoose to create a comment system like in reddit nesting. Here are my schemas i created so far:
var CommentSchema = Schema({
body: {type: String},
chapterId: {type: RK, ref: 'Chapter'},
by: {type: RK, ref: 'User'},
}, {timestamps: true});
var UserSchema = new Schema({
name: String,
username: {type:String, unique: true},
profile_pic: String,
password: String,
role:{type: [{
type: String,
enum: ['user', 'admin']
}],
default: ['user']
}
});

How do I reference another models value in ExpressJs?

I have a model for employee information im using in a MEAN stack and want to reference the store name they will work at in a stores model, would the following be correct?
Employees:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var muv = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
empId: {type: String, required: true, unique: true},
num: {type: String, required: true},
job: {type: String, required: true},
store: {type: Schema.Types.storeName, ref: 'Stores'},
});
schema.plugin(muv);
module.exports = mongoose.model('Message', schema);
Stores:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var schema = new Schema({
storeName: {type: String, required: true},
lat: {type: String, required: true},
long: {type: String, required: true},
});
module.exports = mongoose.model('Stores', schema);
You're close! You want to reference the ID of the store, not the name. When Mongoose does the 'Join', it will see the ObjectID store in the store profile field and match it to an ObjectID in the Stores collection.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var muv = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
empId: {type: String, required: true, unique: true},
num: {type: String, required: true},
job: {type: String, required: true},
store: {type: type: Schema.ObjectId, ref: 'Stores'}, //Reference store ObjectId.
});
schema.plugin(muv);
module.exports = mongoose.model('Message', schema);

Unique index on nested fields in Mongoose schema

Are these schemas valid?
var StudentSchema = new mongoose.Schema({
first_name: {type: String, required:true},
last_name: {type: String, required: true},
mother_name : {type: String, required: true},
siblings:[{
name:{type: String, required: true},
age:{type:Number, required: true},
school:{type:String, required:true}
}]
});
And this
var WinSchema = new mongoose.Schema({
event:{type: mongoose.Schema.Types.ObjectId, ref:'Event'},
winners : [{
student: {type: mongoose.Schema.Types.ObjectId, ref: 'Student'},
position: {type:String, enum:["First","Second","Third","Consolation"]}
}]
});
WinSchema.index({event:1,winners.student:1},{unique:true});
mongoose.model('Win',WinSchema);
Can we nest it as shown in StudentSchema?
Can we create a unique index on nested documents?
Yes you can nest it, see schema example here and of course you can create a index on nested documents here is the example.

Resources