Select specific field from documents in mongoose - node.js

Hi I have three Schemas with this field's
var interactionSchema = new Schema({
pollee: { type: ObjectId, ref: 'Pollee' },
answers: { type: [ObjectId], ref: 'Answer', autopopulate: true },
status: type: String
});
var PolleeSchema = new Schema({
firstName: String,
lastName: String,
gender: String,
user: { type: ObjectId, ref: 'User', required: true },
interactions: { type: [ObjectId], ref: 'Interaction', autopopulate: true }
});
var userSchema = new Schema({
email: String,
pollee: { type: Schema.Types.ObjectId, ref: 'Pollee', autopopulate: true }
});
I need to realize a query in Pollee and pupulate fields from user and interactions, but from interactions I only need the status field, I dont need answers and other ObjectID arrays that contain the Interactions colection.
I made this Query
Pollee.find(req.body.filters)
.select('id age birthday country device_register gender municipality state parish user interactions.status')
.populate('user','email createdAt')
.exec(function(err,pollees){
//Other
}
//....
This return interactions array but status field is not returned. If I write only interactions on the select, return interactions with all fields from interactions.
I try this
Pollee.find(req.body.filters)
.select('id age birthday country device_register gender municipality state parish user')
.populate('user','email createdAt')
.populate('interactions', 'status')
.exec(function(err,pollees){
//Other
}
//....
This return nothing from interactions
I need only Status field from interactions.
The problem here is the interactions field from Pollee Schema, this field its a Array of ObjectsId, and this field its autopopulated from Schema. I want to select only the status field from interactions
Any idea?

I see that you are using mongoose-autopopulate.
It is stated in their document that you can do like this:
var PolleeSchema = new Schema({
//...
interactions: { type: [ObjectId], ref: 'Interaction', autopopulate: { select: 'status' } }
});

Related

infinite population mongoose node js

I have got two models which are ( form, user )
each user has formId field which is the object id of the form object he has
each form has a field called userId which is for the user who has this form
the problem is that I am using mongoose-autopopulate package and if I changed the formId and userId fields to be auto-populated it will open an infinite population with no end
the problem is that some other schemas have a field called formId which is associated with the form object and in this case I want to populate the userId field to get the user info without populating again the formId field.
Schemas Design
const userSchema = new Schema({
name: String,
age: Number,
formId: {
type: Schema.Types.ObjectId,
ref: 'Form',
//this value used to auto populate for mongoose-autopopulate package
autopopulate: true,
},
})
//signing the mongoose-autopopulate plugin
...
//exporting the module
---------------
const formSchema = new Schema({
address: String,
bill: Number,
//the id of the user who added this form
userId: {
type: Schema.Types.ObjectId,
ref: 'User',
//this value used to auto populate for mongoose-autopopulate package
autopopulate: true,
},
})
//signing the mongoose-autopopulate plugin
...
//exporting the module
----------
const orderSchema = new Schema({
products: [],
deliveryBoy: {
type: Schema.Types.ObjectId,
ref: 'Boy',
},
formId: {
type: Schema.Types.ObjectId,
ref: 'Form',
//this value used to auto populate for mongoose-autopopulate package
autopopulate: true,
},
})
//signing the mongoose-autopopulate plugin
...
//exporting the module
Thanks,
Use the maxDepth option mongoose-autopopulate
for example
const orderSchema = new Schema({
products: [],
deliveryBoy: {
type: Schema.Types.ObjectId,
ref: 'Boy',
},
formId: {
type: Schema.Types.ObjectId,
ref: 'Form',
autopopulate: { maxDepth: 2 },
},
})

Inserting data to MongoDB from one schema module to another

I'm using MongoDB with Mongoose, I have to save user data to users collection which contains username, password and company data, *Company data will be having Company name, Address, and website URL
Now what I've done is I've created the different schema for company and users
I need to store user data along with the company ID after installing it into the company collection, for ex.
{
username: "Lorem Ipsum",
password: "Dolar Sit",
company: "5c73afcf9a3bde1a40da5184"
}
something like this (Note: That random string is ID of the company data), but I'll send everything in 1 object like below
{
username: "Lorem Ipsum",
password: "Dolar Sit",
company: {
company_name: "Blah Blah",
company_address: "Blah Blah Blah",
company_website: "BlahBlah.com",
}
}
My user Schema (user.js) is :
const mongoose = require('mongoose');
const Company = require('./company');
Schema = mongoose.Schema
// User Schema
const userSchema = mongoose.Schema({
username:{
type: String,
required: true
},
password:{
type: String,
required: true
},
company:{
type: [{ type: Schema.Types.ObjectId, ref: 'Company' }],
required: true
},
created_on:{
type: Date,
default: Date.now
},
updated_on:{
type: Date,
default: Date.now
}
});
const User = module.exports = mongoose.model('Users', userSchema);
// Add User
module.exports.addUser = (user, callback) => {
User.create(user, callback);
}
And Company Schema is (company.js) :
const mongoose = require('mongoose');
// Book Schema
const companySchema = mongoose.Schema({
company_name:{
type: String
},
target_address:{
type: String
},
target_website:{
type: String
},
created_on:{
type: Date,
default: Date.now
},
updated_on:{
type: Date,
default: Date.now
}
});
const Company = module.exports = mongoose.model('Company', companySchema);
// Add Company
module.exports.addCompany = (comp, callback) => {
Company.create(comp, callback);
}
Now My question is if I run Users.addUser function, and pass the above json to it, it should save/create user along with the company. and company ID should be saved in company property of user collection. if I do get users then it should return User data with company data fetched using that ID saved in the database
How to do that?
If I run the above files and try to insert data to it,
It'll show the below error
'Cast to Array failed for value "{ company_name: \'Moshi Moshi\', company_address: \'Bengaluru\' }" at path "company"',
name: 'CastError',
stringValue:
'"{ company_name: \'Moshi Moshi\', company_address: \'Bengaluru\' }"',
kind: 'Array',
value: [Object],
path: 'company',
reason: [MongooseError] } },
_message: 'Users validation failed',
name: 'ValidationError' }
[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
E:\MoshiMoshi\Projects\Maaamamia\blackhole-rest\models\users.js:17
type: [{ type: ObjectId, ref: 'Company' }],
^
ReferenceError: ObjectId is not defined
how to achive that functionality?
first of all in your user schema company should not be an array because an user will have only single company Id according to your requirement.
//incorrect
company:{
type: [{ type: Schema.Types.ObjectId, ref: 'Company' }],
required: true
},
//correct
company:{
type: Schema.Types.ObjectId,
ref: 'Company',
required: true
},
And second while adding user you are passing entire company object to the company attribute.
first you should add company and then store _id of saved company object into company attribute of user then save user object.
let yourJsonObject={
username: "Lorem Ipsum",
password: "Dolar Sit",
company: {
company_name: "Blah Blah",
company_address: "Blah Blah Blah",
company_website: "BlahBlah.com",
}
}
let companyObject=yourJsonObject.company;//your company object
let userObject= yourJsonObject //your user object
let savedCompanyObject= //call add company method of your
//model with companyObject data
userObject.company = savedCompanyObject._id;
//now pass userObject to your addUser method of user model

Is it possible to populate a field in mongoose which has other information on it too?

This is the relevant portion of my Schema:
var classroomSchema = mongoose.Schema({
students: [{
_id: mongoose.Schema.Types.ObjectId,
ref: 'User',
rate: {
type: Number,
default: 200,
},
referrals: [mongoose.Schema.Types.ObjectId],
}],
)};
Here rate and referrals are properties of the students which are valid in the context of that classroom, and cannot be populated from the Students model.
Is there any way to define my schema such that I can keep those fields(rate and referrals) and also use populate to link other fields such as name, age, etc of the student?
Change your schema to this:
var classroomSchema = mongoose.Schema({
students: [{
rate: { type: Number, default: 200 },
user: { ref: 'User', type: Schema.Types.ObjectId },
referrals: [mongoose.Schema.Types.ObjectId],
}],
});
Usage:
classroom
.findOne(...)
.populate('user')
.exec((err, classroom) => {
let student0 = classroom.students[0];
// student0.rate
// student0.user.name
});

How to name a foreign key different from db name in mongoose

Is there a way in mongoose + Node.js/Express to define the relation between the foreign key field and what I refer to that field in the model is? My issue is that I have a mongo database where my foreign keys are all formatted like 'exampleId' instead of 'example'. I could just call out 'exampleId' directly but then it leads to weird things like when I populate 'exampleId' instead of 'example' (which is confusing because once populated, it is now the 'example' itself instead of its id).
Here is how I do it now and it works with my graphQL server, but only if my field in the database is 'course' while my database's field is 'courseId'
const CourseSchema = new Schema({
_id: { type: String },
sections: [{
type: Schema.Types.String,
ref: 'Section'
}],
});
const SectionType = new GraphQLObjectType({
name: 'SectionType',
fields: () => ({
id: { type: GraphQLID },
courseId: {
type: require('./course_type'),
resolve(parentValue) {
return Section.findById(parentValue)
.populate('course')
.then(section => section.course);
}
},
}),
});
I figured it out! With the newest version of mongoose, you actually can use virtual fields to accomplish what I wanted to do and this technique allows for flexibility in laying out your schema. Say that my MongoDB collections look like the following:
Courses { _id, sectionIds }
Lectures { _id, courseId }
I can use the following schema in mongoose and it will allow me to refer to course.lectures or lecture.course instead of the usual course.lectureIds or section.courseId:
const CourseSchema = new Schema({
_id: { type: String },
});
CourseSchema.virtual('sections', {
type: Schema.Types.String,
ref: 'Section',
localField: 'sectionIds',
foreignField: '_id',
justOne: false,
});
CourseSchema.statics.findSections = function(id) {
return this.findById(id)
.populate('sections')
.then(course => course.sections);
}
const SectionSchema = new Schema({
_id: { type: String },
});
SectionSchema.virtual('course', {
type: Schema.Types.String,
ref: 'Course',
localField: 'courseId',
foreignField: '_id',
justOne: true,
});
Actually MongoDB isn't a relational database. You can alter the field and its name whatever you like. Ex I Have an Owner(Meteor.users) table and Patient Table with this column
ownerid : {type: String, min: 1},
firstname: {type: String, min: 1},
lastname: {type: String, min: 1},
middlename: {type: String, min: 1, optional: true},
createdbyid: { type: String },
createdbyname: { type: String },
createdat: { type: Date, defaultValue: new Date() },
updatedbyid: { type: String, optional: true },
updatedbyname : { type: String, optional: true },
updatedat: { type: Date, defaultValue: new Date() },
I can easily stamp the value of my {Meteor.Users()._id} to ownerid of my designated patient by just processing them at meteor.methods. You don't have to worry about foreign keys mongo doesn't do relational databases you can customize your database whatever you like. I Hope this helps ;)
Mongoose Documentation posits that _id has to be used in refs and that[i]t is important to match the type of _id to the type of ref. , e.g.:
var personSchema = Schema({
_id : Number, //it is `Number`
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String,
fans : [{ type: Number, ref: 'Person' }] // use `Number` to match
});
I also wonder if by 'database' you mean 'collection'.

How to compare _id value of Models made using Mongoose?

I have the following two schemas of User and Critique and I've got the data persisted in MongoDB database:
var userSchema = mongoose.Schema({
critiques: [{ type: Schema.ObjectId, ref: 'Critique' }],
});
var User = mongoose.model("User", userSchema);
var critiqueSchema = mongoose.Schema({
author: {type: String, default: ''},
date: { type: Date, default: Date.now },
comment: { type: String, default: '' },
stars: { type: Number, default: 0 },
_user: { type: Schema.ObjectId, ref: 'User' }
});
var Critique = mongoose.model("Critique", critiqueSchema);
user.critiques[0]._id.equals(critique._id) is giving me undefined is not a function.
How to compare _id value of a User instance with the Critique instance?
The critiques field of your user object directly contains an array of ObjectIds, so it would just be:
user.critiques[0].equals(critique._id)
user.critiques would only contain full Critique objects if you chained a .populate('critiques') call in the find where you obtained user.

Resources