Accessing subdocument properties in mongoose - node.js

I am using a MEAN stack to build this application.
Here is my subject.js schema:
var mongoose = require('mongoose');
var schema = mongoose.Schema;
var topics = require('./topic');
var subjectSchema = new schema({
_category : {
type: String,
default: ""
},
topics: [topics.schema]
});
module.exports = mongoose.model('Subject', subjectSchema);
and my topics.js schema:
var mongoose = require('mongoose');
var schema = mongoose.Schema;
var otherstuff = require('./otherstuff');
var otherstuff2 = require('./otherstuff2');
var topicSchema = new schema ({
title: String,
otherstuff: [mongoose.model('otherstuff').schema],
otherstuff2: [mongoose.model('otherstuff2').schema]
});
module.exports = mongoose.model('Topic', topicSchema);
What I am having difficulty with is how to access my topicSchema to populate it with forms from my front end.
I can save information to the subjectSchema, but not the sub documents.
I have tried using this as outlined in another article:
var Subject = mongoose.model('Subject', subjectSchema);
Subject.find({}).populate('subjects[0].topics[0].title').exec(function(err, subjects) {
console.log(subjects[0].topics[0].title);
});
But I continue to get TypeError: Cannot read property 'title' of undefined. How do I access the title property?

populate in mongoose is used to populate referenced documents, that are marked with ref attribute (see more info in the docs). Sub-documents on the other hand are available when do a simple query because they are actually an array of custom objects, so if you remove the populate method your query will work as expected:
Subject.find({}).exec(function(err, subjects) {
console.log(subjects[0].topics[0].title);
});

Related

How do I update the existing documents' schema?

I'm using mongoose to do some MongoDB operations.
At the beginning the category was number,
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const sampleSchema = new Schema({
category: {
type: Number,
}
})
module.exports = mongoose.model("SampleSchema", sampleSchema);
Now the category changed to String, So I changed the model like this
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const sampleSchema = new Schema({
category: {
type: String,
}
})
module.exports = mongoose.model("SampleSchema", sampleSchema);
The problem is, I have already inserted 200 records into this collection. Is there any way to update the category value with a string and change its type to string?
Please get All data by query and update it one by one in loop.
Like:
db.tableName.find( { 'status' : { $type : 1 } } ).forEach( function (val) {
val.status = new String(val.status);
db.tableName.save(val);
});
I changed the category to mixed, that's working fine with numbers and string.
Thanks for the help #prasad_

Mongoose update the field of the nested document not working

I've tried to update the field of the nested sub document using mongoose.
Here are the model and source code.
Model
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var info_schema = mongoose.schema({
info:Schema.Types.Mixed,
},{collection:'info'});
var InfoModel = mongoose.model('info', info_schema);
I've tried to execute db.info.updateMany({'info.addition.group':myid},{$set:{'info.addition.field1':'a','info.addition.field2':'b'}}) in mongoshell.
It worked well,but it didn't work using mongoose.
InfoModel.updateMany({'info.addition.group':myid},{$set:{'info.addition.field1':'a','info.addition.field2':'b'}}).exec();
Why doesn't mongoose update the field of the sub nested document?
So I tried to described the model in more detail.
var info_schema = mongoose.schema({
info:{
addition:Schema.Types.Mixed,
otherinfo:String,
modified:Number,
....
},
},{collection:'info'});
At this time , mongoose threw out the error.
CastError: Cast to number failed for value "a" at path "addition"
What did I do incorrectly?
What is the reason of this?
This works using your code and modifying it a little bit:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var info_schema = new Schema({ // <-- just use Schema
info: Schema.Types.Mixed
},{collection:'info'});
var InfoModel = mongoose.model('info', info_schema);
InfoModel.updateMany({'info.addition.group': 1}, // <-- I used 1 for testing
{ $set: { 'info.addition.field1' : 'a', 'info.addition.field2' : 'b' } }).exec()
Tested locally after first creating a record with info.addition.id == 1 so that I can update it etc.

How to implement more than one collection in get() function?

My model university.js
const mongoose = require('mongoose');
const UniversitySchema = mongoose.Schema({
worldranking:String,
countryranking:String,
universityname:String,
bachelorprogram:String,
masterprogram:String,
phdprogram:String,
country:String
},{collection:'us'});
const University =module.exports = mongoose.model('University',UniversitySchema);
My route.js
const express = require('express');
const router = express.Router();
const University = require('../models/university');
//retrieving data
//router.get('/universities',(req,res,next)=>{
// University.find(function(err,universities){
// if(err)
// {
// res.json(err);
//}
// res.json(universities);
//});
//});
router.get('/usa',function(req,res,next){
University.find()
.then(function(doc){
res.json({universities:doc});
});
});
module.exports= router;
How to implement multiple collections in this get() function? I put my collection name in the model. Please help me with a solution to call multiple collections in get() function.
Here is Example to use multiple collection names for one schema:
const coordinateSchema = new Schema({
lat: String,
longt: String,
name: String
}, {collection: 'WeatherCollection'});
const windSchema = new Schema({
windGust: String,
windDirection: String,
windSpeed: String
}, {collection: 'WeatherCollection'});
//Then define discriminator field for schemas:
const baseOptions = {
discriminatorKey: '__type',
collection: 'WeatherCollection'
};
//Define base model, then define other model objects based on this model:
const Base = mongoose.model('Base', new Schema({}, baseOptions));
const CoordinateModel = Base.discriminator('CoordinateModel', coordinateSchema);
const WindModel = Base.discriminator('WindModel', windSchema);
//Query normally and you get result of specific schema you are querying:
mongoose.model('CoordinateModel').find({}).then((a)=>console.log(a));
In Short,
In mongoose you can do something like this:
var users = mongoose.model('User', loginUserSchema, 'users');
var registerUser = mongoose.model('Registered', registerUserSchema, 'users');
This two schemas will save on the 'users' collection.
For more information you can refer to the documentation: http://mongoosejs.com/docs/api.html#index_Mongoose-model or you can see the following gist it might help.
Hope this may help you. You need to modify according to your requirements.

Querying result from mongoose using dynamic model.find

I need to find the results of a query with mongoose find({}) method in Node.js with a variable containing model name.
var adSchema = new Schema({ schema defination });
var Ad = mongoose.model('Ad', adSchema);
var variableName = 'Ad';
variableName.find({}).exec(function (err, adObj) {});
Is it possible or not?
Thanks in advance
You should be able to do that when calling model with just the name like so
mongoose.model('Ad').find({}).exec(function (err, adObj) {});
See here for the corresponding part of the official docs
Try this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var anySchema = new Schema({
fieldname: String
});
var Test = mongoose.model('Test', anySchema);
Test.find({}).exec(function(err,result){});

is it possible to reference a subdocument schema in mongoose?

is it possible to reference a sub document schema in mongoose ?
just like below
var sectionSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true}
});
var courseSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true},
sections:[sectionSchema]
});
var studentSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true},
course:{type:mongoose.Schema.Types.ObjectId,ref: 'courseSchema'},
section:{type:mongoose.Schema.Types.ObjectId,ref: 'sectionSchema'},
contactnumber:{type:String,required:true},
parentname:{type:String,required:true}
});
var schoolSchema = mongoose.Schema(
{
id:{type:String,required:true},
name:{type:String,required:true,unique:true},
address:{type:String,required:true},
year:{type:String,required:true},
contactnumber:{type:String,required:true},
courses:[courseSchema],
students:[studentSchema]
});
var School = mongoose.model('School',schoolSchema);
in the above model i have section inside course which is inside school document.
i have students schema which is inside school document i want course to point to course schema and section to point to section schema.so is it possible to refer a sub document schema in mongoose.

Resources