Get the populated data associated with ref in mongoose - node.js

I have two schemas: 'Leads' and 'LeadsCategory'.
Leads Schema:
const id = mongoose.Schema.Types.ObjectId;
const leadsSchema = mongoose.Schema(
{
_id: id,
userId: { type: id, ref: "User", required: true },
leadName: String,
leads: [
{
_id: id,
name: String,
mobile: Number,
address: String,
education: {
school: String,
graduation: String
},
leadType: { type: id, ref: "LeadsCategory", required: true }
}
]
},
{
timestamps: true
}
);
module.exports = mongoose.model("lead", leadsSchema);
Leads Category Schema:
const id = mongoose.Schema.Types.ObjectId;
const leadsCategorySchema = mongoose.Schema({
_id: id,
name: {
type: String,
required: true
},
leadsData: [{ type: id, ref: 'lead' }]
},
{ timestamps: true }
);
module.exports = mongoose.model("LeadsCategory", leadsCategorySchema);
I'm referencing the leadsCategory as soon as new lead is created and it does populate my leadsCategory into the Leads controller.
So my final data inside 'Leads collection' looks like this:
[
{
"_id": "5e8832dde5d8273824d86502",
"leadName": "Freshers",
"leads": [
{
"education": {
"school": "LPS",
"graduation": "some school"
},
"location": {
"state": "delhi",
"country": "india"
},
"name": "Joey",
"mobile": 1524524678,
"_id": "5e8832dde5d8273824d86500",
"leadType": {
"_id": "5e88285f5dda5321bcc045a6",
"name": "all"
}
},
{
"education": {
"school": "DAV",
"graduation": "some school"
},
"location": {
"state": "delhi",
"country": "india"
},
"name": "Ben",
"mobile": 1524524678,
"_id": "5e8832dde5d8273824d86501",
"leadType": {
"_id": "5e88285f5dda5321bcc045a6",
"name": "all"
}
}
]
}
]
But now I need to associate the leads data into my 'leadsCategory' collection so that I can query the leads data according to the leadType created. For now, I have only one 'leadType':'all'. But further, I will create more types and populate the data accordingly.
I tried something like this:
exports.get_leads_type_all = (req, res) => {
LeadsCategory.find()
.populate('leadsData')
.then( data => {
res.json(data)
})
}
But this returns me only empty array like this:
{ "leadsData": [],
"_id": "5e88285f5dda5321bcc045a6",
"name": "all",
"createdAt": "2020-04-04T06:25:35.171Z",
"updatedAt": "2020-04-04T06:25:35.171Z",
"__v": 0
},
Please help me to associate and related this data. I have tried lot's of thins but could not make it work.

try this:
exports.get_leads_type_all = (req, res) => {
LeadsCategory.find()
.populate('leadsData')
.execPopulate()
.then( data => {
res.json(data)
})
}
https://mongoosejs.com/docs/api/document.html#document_Document-execPopulate

Related

Querying nested objects using find not working in mongoose (MongoDB)

I'm trying to get an object which has isDraft value true, but I'm also getting objects which have isDraft value false. I need only objects having isDraft value true. I have tried all possible ways but am not able to find a solution for this. Can anyone help me with this?
Below are the schema, query and response.
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Contract = new Schema({
name: {
type: String,
unqiue: true,
required: true
},
version: [
{
no: {
type: Number,
required: true
},
sections: [
{
sectionName: {
type: String,
required: true
},
clause: [{
description: {
type: String,
required: true
},
}]
}
],
approvedBy: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
}
],
acceptedBy: [
{
name: {
type: String,
},
eamil: {
type: String,
},
}
],
isDraft: {
type: Boolean,
required: true
},
date: {
type: Date,
default: Date.now
}
}
],
createdBy: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
});
module.exports = mongoose.model('contract', Contract);
Query
query = {
$and: [
{ createdBy: clientAdminDetails._id },
{ "version.isDraft": true }
],
};
await Contract
.find(query)
.skip(req.body.noOfItems * (req.body.pageNumber - 1))
.limit(req.body.noOfItems)
.exec((err, contract) => {
if (err) {
return res.json(err);
}
Contract.countDocuments(query).exec((count_error, count) => {
if (err) {
return res.json(count_error);
}
return res.json({
total: count,
page: req.body.pageNumber,
pageSize: contract.length,
contracts: contract
});
});
});
Response
{
"total": 1,
"page": 1,
"pageSize": 1,
"contracts": [
{
"_id": "61449469775..",
"name": "Octavia Blankenship",
"version": [
{
"_id": "614496593cc..",
"sections": [
{
"_id": "61449469775..",
"sectionName": "Est dolore dolorem n Updated `1323",
"clause": [
{
"_id": "614494697..",
"description": "Numquam nostrud et a"
}
]
}
],
"isDraft": false,
"no": 1,
"approvedBy": [],
"acceptedBy": [],
"date": "2021-09-17T13:21:29.509Z"
},
{
"_id": "614496122904ee4e046fbee8",
"sections": [
{
"_id": "6144955a8c0061025499606f",
"sectionName": "Praesentium suscipit",
"clause": [
{
"_id": "6144955a8c00610254996070",
"description": "Velit aperiam ut vel"
}
]
}
],
"isDraft": true,
"no": 2,
"approvedBy": [],
"acceptedBy": [],
"date": "2021-09-17T13:20:18.128Z"
}
],
"createdBy": "614367e980b29e6c...",
"__v": 0
}
]
}
This is why using your query you are telling mongo "Give me a document where createdBy is desired id and version.isdraft is true" So, as the DOCUMENT contains both values, is returned, even existing false into the array.
To solve this you have many ways.
First one is using $elemMatch into projection (docs here). But using this way only the first element is returned, so I think you prefer other ways.
So you can use an aggregation query using $filter like this:
First $match by values you want (as in your query).
Then override version array filtering by values where isDraft = true.
db.collection.aggregate([
{
"$match": {
"createdBy": "",
"version.isDraft": true
}
},
{
"$set": {
"version": {
"$filter": {
"input": "$version",
"as": "v",
"cond": {
"$eq": [
"$$v.isDraft",
true
]
}
}
}
}
}
])
Example here

How to exclude an fields from populated query data? [duplicate]

This question already has answers here:
Mongoose/Mongodb: Exclude fields from populated query data
(4 answers)
Closed 2 years ago.
I just not want to pass user id in discussion array.
Now I getting back from this route like this.
{
"_id": "5f4600ab7ec81f6c20f8608d",
"name": "2",
"category": "2",
"description": "2",
"deadline": "2020-08-10",
"discussion": [
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089bd265ec85b896f8491",
"user": {
"_id": "5f5089a2265ec85b896f848f",
"userName": "MdJahidHasan01"
},
"text": "3"
},
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089ae265ec85b896f8490",
"user": {
"_id": "5f5089a2265ec85b896f848f",
"userName": "MdJahidHasan01"
},
"text": "2"
}
]
}
But I want to get like this
{
"_id": "5f4600ab7ec81f6c20f8608d",
"name": "2",
"category": "2",
"description": "2",
"deadline": "2020-08-10",
"discussion": [
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089bd265ec85b896f8491",
"user": {
"userName": "MdJahidHasan01"
},
"text": "3"
},
{
"date": "2020-09-03T06:12:15.881Z",
"_id": "5f5089ae265ec85b896f8490",
"user": {
"userName": "MdJahidHasan01"
},
"text": "2"
}
]
}
Select does not working here. I just not want to pass user id in discussion array just username.
As I use user id for authorization. So it is not an good idea to send user id.
Project Model
const mongoose = require('mongoose');
const projectSchema = new mongoose.Schema({
name: {
type: String,
require: true
},
category: {
type: String,
require: true
},
description: {
type: String,
require: true
},
deadline: {
type: String,
require: true
},
discussion: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
date: {
type: Date,
default: Date.now()
},
text: {
type: String,
require: true
}
}
]
});
module.exports = mongoose.model('Project', projectSchema);
Project Details Route
router.get('/:projectId',async (req, res) => {
try {
const project = await Project.findById(req.params.projectId)
.populate('discussion.user', 'userName')
.select('-discussion.user._id')
console.log(project);
await res.status(200).json(project);
} catch (error) {
console.log(error);
return res.status(400).json({ 'error': 'Server Error' });
}
})
Just add this after the .populate:
delete project.discussion._id

mongodb insert into array of objects

I need to find the element by id, then go into the array of objects, find the desired by id and add the field guessId into it and insert the id key into it and assign the array of id. How can I do that ?
https://jsoneditoronline.org/?id=442f1dae0b2d4997ac69d44614e55aa6
In general, I need to create a GuessId field with such a structure
in fact, I am doing the voting, that is, the key in guessId will be go to vote, and the array to it, this is users who vote
{
"_id": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"bio": {
"firstname": "Лена",
"lastname": "фыв",
"middlename": "",
"company": "вв"
},
"files": [
{
"_id": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"info": {
"size": 20805727,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Ахуевший Ленусик (Банк русский стандарт). Выпуск #5..mp3",
"fieldname": "selectedFile"
},
"userId": "5e05da745b21e61ccc84a892",
"date": "2019-12-27T10:19:12.213Z"
},
{
"_id": "81b94dea-ece6-421c-b68a-0aa59332cd0d",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "81b94dea-ece6-421c-b68a-0aa59332cd0d.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\81b94dea-ece6-421c-b68a-0aa59332cd0d.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"info": {
"size": 13515683,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Выпуск #75 Попрошайка НСВ..mp3",
"fieldname": "selectedFile"
},
"userId": "5e05da745b21e61ccc84a892",
"date": "2019-12-27T10:25:37.710Z"
}
],
"date": "2019-12-27T10:19:12.213Z",
"__v": 1
}
Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const HabalkaSchema = new Schema({
_id: {
type: String
},
bio: {
firstname: String,
lastname: String,
middlename: String,
company: String
},
files: [
{
_id: {
type: String
},
destination: {
type: String
},
filename: {
type: String
},
path: {
type: String
},
folder: {
type: String
},
info: {
size: {
type: Number
},
mimetype: {
type: String
},
encoding: {
type: String
},
originalname: {
type: String
},
fieldname: {
type: String
},
},
date: {
type: Date,
default: Date.now
},
bio: {
type: Object
},
userId: String,
guessId: {},
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Habalka = mongoose.model('habalka', HabalkaSchema);
You can use the positional $ operator like this:
router.put("/habalka/:id/:fileId/:guessId", async (req, res) => {
const result = await Habalka.findOneAndUpdate(
{
_id: req.params.id,
"files._id": req.params.fileId
},
{
"files.$.guessId": {
[req.params.guessId]: ["a", "b"] //todo: get this array from req.body
}
},
{
new: true
}
);
res.send(result);
});
Route url: http://..../habalka/f58482b1-ae3a-4d8a-b53b-ede80fe1e225/2e4e40c7-4df6-4974-8d16-bb24cd8134d6/asda2
This will give you a result like this in the given file:
"files": [
{
"info": {
"size": 20805727,
"mimetype": "audio/mp3",
"encoding": "7bit",
"originalname": "Ахуевший Ленусик (Банк русский стандарт). Выпуск #5..mp3",
"fieldname": "selectedFile"
},
"date": "2019-12-27T10:19:12.213Z",
"_id": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6",
"destination": "./uploads/f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"filename": "2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"path": "uploads\\f58482b1-ae3a-4d8a-b53b-ede80fe1e225\\2e4e40c7-4df6-4974-8d16-bb24cd8134d6.mp3",
"folder": "f58482b1-ae3a-4d8a-b53b-ede80fe1e225",
"userId": "5e05da745b21e61ccc84a892",
"guessId": {
"asda2": [
"a",
"b"
]
}
},
And later if you want to add an item inside one of the guessId arrays, you can use the following code:
router.put("/habalka/:id/:fileId/:guessId", async (req, res) => {
const result = await Habalka.findOneAndUpdate(
{
_id: req.params.id,
"files._id": req.params.fileId
},
{ $push: { [`files.$.guessId.${req.params.guessId}`]: "c" } },
{
new: true
}
);
res.send(result);
});

Mongoose upsert without deleting existing fields

The goal of my code is to upsert an object into my database. I created the Schema which is a bit complex
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const objectSchema = new Schema(
{ message: String },
{ discriminatorKey: "type", _id: false }
);
const cameraSchema = new Schema(
{
number: { type: Number, required: true },
name: { type: String, required: true } //Do not update if exists
},
{ _id: false }
);
const mainSchema = new Schema(
{
name: { type: String, required: true, trim: true },
lastUpdateTime: { type: Date, default: Date.now },
objects: [objectSchema]
},
{ collection: "mainCollection" }
);
mainSchema.path("objects").discriminator(
"TypeA",
new Schema(
{
cameras: [cameraSchema],
enabled: { type: Boolean } //Do not update if exists
},
{ _id: false }
)
);
mainSchema.path("objects").discriminator(
"TypeB",
new Schema(
{
available: { type: Boolean, required: true },
enabled: { type: Boolean } //Do not update if exists
},
{ _id: false }
)
);
module.exports = mongoose.model("mainModel", mainSchema);
I am receiving the following object from an external source
{
"name": "040C7",
"objects": [
{
"type": "TypeA",
"cameras": [
{
"number": 1
},
{
"number": 2
},
{
"number": 3
}
]
},
{
"type": "TypeB",
"available": false
}
]
}
If the name exists in my database, I should update every field that I received without removing/updating the fields :
enabled in TypeA and TypeB
name in the camera objects
Otherwise, I should insert it in the database with all the fields and default values for enabled (true) and name (Camera)
I already tried the UpdateOne() function but it is deleting my fields enabled and name when they already are in my database
const obj = new myModel(message);
let upsertObj = obj.toObject();
delete upsertRcm._id;
MyModel.updateOne(
{ name: obj.name },
upsertObj,
{ upsert: true },
err => {
console.log(err)
}
);
How can I say to mongoose to keep fields that are already in my database but not in my received object ?
Document in database
{
"lastUpdateTime": "2018-11-07T09:12:30.750Z",
"name": "040C7",
"objects": [
{
"type": "TypeA",
"enabled": true,
"cameras": [
{
"number": 1,
"name": "Camera",
}
]
},
{
"type": "TypeB",
"enabled": true,
"available": false
}
]
}
After the update with the received object
{
"lastUpdateTime": "2018-11-07T09:14:30.600Z",
"name": "040C7",
"objects": [
{
"type": "TypeA",
"cameras": [
{
"number": 1,
},
{
"number": 2,
},
{
"number": 3,
}
]
},
{
"type": "TypeB",
"available": false
}
]
}
But it should be
{
"lastUpdateTime": "2018-11-07T09:14:30.600Z",
"name": "040C7",
"objects": [
{
"type": "TypeA",
"enabled": true
"cameras": [
{
"number": 1,
"name": "Camera"
},
{
"number": 2,
},
{
"number": 3,
}
]
},
{
"type": "TypeB",
"enabled": true,
"available": false
}
]
}
MongoDB version: 4.0.2
The name field is my unique identifier. Only one type "TypeA", "TypeB", ... will be present in the array. I will never receive 2 "TypeA" in my objects
The list of fields that have to be updated :
objects["TypeA"].cameras.number (value from new object)
objects["TypeB"].available (value from new object)
lastUpdateTime (Date now)
The list of fields that are in the database and should kept :
objects["TypeA"].enabled
objects["TypeA"].cameras.name
objects["TypeB"].enabled

Improving Mongoose Schema for Course Subscription App

I am new to mongodb, and playing around with a self-project, where user can subscribe to 3-4 different courses that are predefined. Each course is 1 hour long course everyday, and students can subscribe for either 15, 30 or more days.
App will store information of the students, the course they subscribed for (how many) days and days they were present for the course.
This is my Mongoose Schema.
var mongoose = require('mongoose');
var schemaOptions = {
timestamps: true,
toJSON: {
virtuals: true
}
};
var courseSchema = new mongoose.Schema({
name: String
});
var studentSchema = new mongoose.Schema({
name: String,
email: { type: String, unique: true},
phone: String,
gender: String,
age: String,
city: String,
street: String,
picture: String,
course: [courseSchema],
subscriptionDays: Number,
daysPresent: [Date]
}, schemaOptions);
module.exports = mongoose.model('Student', studentSchema);
Here, course is any of 3-4 courses, one student can subscribe one or more course at same time. subscriptionDays is the number of days they subscribe to, and daysPresent are the days they took the course.
I am not sure if this is the right schema for my project, so far I was able to do this much.
Confusions with the schema are:
When student who is subscribed to two different courses arrives to the
institute, but takes only one class (course), then I do not think this
schema supports the case, for this I thought to modify courseSchema like this,
var courseSchema = new mongoose.Schema({
name: String,
subsriptionDays: Number,
daysPresent: [Date]
});
But, after doing this I am still confused to make changes on the data, like Date has to be inserted into the documents every time student attends for the course.
Second confusion is how will I update the data inside document every day, only the data that has to be inserted on daily basis is the Date inside days.
Can I get some guidance and suggestion from Mongo Experts? TIA
I think that you are basically on the right track with your second thoughts on extending the design. I would really only expand on that by also including a "reference" to the "Course" itself as opposed to just the information embedded on the schema.
As your usage case questions, then they are probably best addressed with a working example:
const async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.Types.ObjectId;
mongoose.set('debug',true);
mongoose.connect('mongodb://localhost/school');
// Course model
const courseSchema = new Schema({
name: String,
info: String
});
const Course = mongoose.model('Course', courseSchema);
// Student Model
const studentCourseSchema = new Schema({
_id: { type: ObjectId, ref: 'Course' },
name: String,
subscriptionDays: Number,
daysPresent: [Date]
});
const studentSchema = new Schema({
name: String,
email: String,
courses: [studentCourseSchema]
});
studentSchema.index({ "email": 1 },{ "unique": true, "background": false });
const Student = mongoose.model('Student', studentSchema);
function logOutput(content) {
console.log( JSON.stringify( content, undefined, 2 ) )
}
async.series(
[
// Clear collections
(callback) =>
async.each(mongoose.models,
(model,callback) => model.remove({},callback),callback),
// Set up data
(callback) =>
async.parallel(
[
(callback) => Course.insertMany(
[
{ "name": "Course 1", "info": "blah blah blah" },
{ "name": "Course 2", "info": "fubble rumble" }
],
callback),
(callback) => Student.insertMany(
[
{ "name": "Bill", "email": "bill#example.com" },
{ "name": "Ted", "email": "ted#example.com" }
],
callback)
],
callback
),
// Give bill both courses
(callback) => {
async.waterfall(
[
(callback) => Course.find().lean().exec(callback),
(courses,callback) => {
courses = courses.map(
course => Object.assign(course,{ subscriptionDays: 5 }));
let ids = courses.map( c => c._id );
Student.findOneAndUpdate(
{ "email": "bill#example.com", "courses._id": { "$nin": ids } },
{ "$push": {
"courses": {
"$each": courses
}
}},
{ "new": true },
(err, student) => {
logOutput(student);
callback(err);
}
)
}
],
callback
)
},
// Attend one of bill's courses
(callback) => Student.findOneAndUpdate(
{ "email": "bill#example.com", "courses.name": 'Course 2' },
{ "$push": { "courses.$.daysPresent": new Date() } },
{ "new": true },
(err, student) => {
logOutput(student);
callback(err);
}
),
// Get Students .populate()
(callback) => Student.find().populate('courses._id')
.exec((err,students) => {
logOutput(students);
callback(err);
}
)
],
(err) => {
if (err) throw err;
mongoose.disconnect();
}
)
So that should give you a sample of how the operations you ask about actually work.
Add a course to the student Shows addition of a couple of courses where I think you would ideally use $push functionality of MongoDB. To ensure that you are not adding courses that are already there the "query" expression actually excludes selection if they are already present in the courses array. In the example a "list" is passed, so we use $nin but with a single item you would simply use $ne:
{ "email": "bill#example.com", "courses._id": { "$nin": ids } },
{ "$push": { "courses": { "$each": courses } } },
Add an attended date This actually demonstrates a case where you would want to "positionally match" the item within "courses" in order to know which one to update. This is done by providing much like before a condition to "match" as opposed to "exclude" the specific array element. Then in the actual "update" part, we apply the same $push operator so we can append to the "daysPresent"array, but also using the positional $ operator to point to the correct array index position which corresponds to the match condition:
{ "email": "bill#example.com", "courses.name": 'Course 2' },
{ "$push": { "courses.$.daysPresent": new Date() } },
As a bonus there are a few more operations in there showing the relational nature between keeping a list of "Courses" in their own collection with additional information that you probably do not want to embed on each student.
The last operation in the sample actually performs a .populate() to actually pull in this information from the other collection for display.
The whole example has debugging turned on with mongoose.set('debug',true); so you can see what the actual calls to MongoDB are really doing for each operation.
Also get acquainted with the .findOneAndUpdate() method used here, as well as the various "update operators" from the core MongoDB documentation.
Sample output
Mongoose: courses.remove({}, {})
Mongoose: students.remove({}, {})
Mongoose: students.ensureIndex({ email: 1 }, { unique: true, background: false })
(node:10544) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
Mongoose: courses.insertMany([ { __v: 0, name: 'Course 1', info: 'blah blah blah', _id: 5944d5bc32c6ae2930174289 }, { __v: 0, name: 'Course 2', info: 'fubble rumble', _id: 5944d5bc32c6ae293017428a } ], null)
Mongoose: students.insertMany([ { __v: 0, name: 'Bill', email: 'bill#example.com', _id: 5944d5bc32c6ae293017428b, courses: [] }, { __v: 0, name: 'Ted', email: 'ted#example.com', _id: 5944d5bc32c6ae293017428c, courses: [] } ], null)
Mongoose: courses.find({}, { fields: {} })
Mongoose: students.findAndModify({ 'courses._id': { '$nin': [ ObjectId("5944d5bc32c6ae2930174289"), ObjectId("5944d5bc32c6ae293017428a") ] }, email: 'bill#example.com' }, [], { '$push': { courses: { '$each': [ { daysPresent: [], _id: ObjectId("5944d5bc32c6ae2930174289"), name: 'Course 1', subscriptionDays: 5 }, { daysPresent: [], _id: ObjectId("5944d5bc32c6ae293017428a"), name: 'Course 2', subscriptionDays: 5 } ] } } }, { new: true, upsert: false, remove: false, fields: {} })
{
"_id": "5944d5bc32c6ae293017428b",
"__v": 0,
"name": "Bill",
"email": "bill#example.com",
"courses": [
{
"subscriptionDays": 5,
"name": "Course 1",
"_id": "5944d5bc32c6ae2930174289",
"daysPresent": []
},
{
"subscriptionDays": 5,
"name": "Course 2",
"_id": "5944d5bc32c6ae293017428a",
"daysPresent": []
}
]
}
Mongoose: students.findAndModify({ 'courses.name': 'Course 2', email: 'bill#example.com' }, [], { '$push': { 'courses.$.daysPresent': new Date("Sat, 17 Jun 2017 07:09:48 GMT") } }, { new: true, upsert: false, remove: false, fields: {} })
{
"_id": "5944d5bc32c6ae293017428b",
"__v": 0,
"name": "Bill",
"email": "bill#example.com",
"courses": [
{
"subscriptionDays": 5,
"name": "Course 1",
"_id": "5944d5bc32c6ae2930174289",
"daysPresent": []
},
{
"subscriptionDays": 5,
"name": "Course 2",
"_id": "5944d5bc32c6ae293017428a",
"daysPresent": [
"2017-06-17T07:09:48.662Z"
]
}
]
}
Mongoose: students.find({}, { fields: {} })
Mongoose: courses.find({ _id: { '$in': [ ObjectId("5944d5bc32c6ae2930174289"), ObjectId("5944d5bc32c6ae293017428a") ] } }, { fields: {} })
[
{
"_id": "5944d5bc32c6ae293017428b",
"__v": 0,
"name": "Bill",
"email": "bill#example.com",
"courses": [
{
"subscriptionDays": 5,
"name": "Course 1",
"_id": {
"_id": "5944d5bc32c6ae2930174289",
"__v": 0,
"name": "Course 1",
"info": "blah blah blah"
},
"daysPresent": []
},
{
"subscriptionDays": 5,
"name": "Course 2",
"_id": {
"_id": "5944d5bc32c6ae293017428a",
"__v": 0,
"name": "Course 2",
"info": "fubble rumble"
},
"daysPresent": [
"2017-06-17T07:09:48.662Z"
]
}
]
},
{
"_id": "5944d5bc32c6ae293017428c",
"__v": 0,
"name": "Ted",
"email": "ted#example.com",
"courses": []
}
]
Schema you can define like:-
var mongoose = require('mongoose');
var courseSchema = new mongoose.Schema({
name: String
});
var studentSchema = new mongoose.Schema({
name: String,
email: { type: String, unique: true},
phone: String,
gender: String,
age: String,
city: String,
street: String,
picture: String,
courses: [{
course:{type:mongoose.Schema.Types.ObjectId,ref:'courseSchema'},
isAttending:{type:Boolean ,default:false}
}],
subscriptionDays: Number,
daysPresent: [Date]
}, schemaOptions);
module.exports = mongoose.model('Student', studentSchema);
isAttending will solve your problem if studen subscribe 3 courses and going to particular one course then isAttending will be true otherwise false.
You Can use Cron npm module which will run a function on what time will you set and its make your life easy.
Thanks

Resources