How to populate nested model in mongoose - node.js

I have dataSubmitted model:
module.exports = (mongoose, mongoosePaginate) => {
const schema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
company: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
}, {
timestamps: true
})
schema.plugin(mongoosePaginate)
const dataSubmitted = mongoose.model('dataSubmitted', schema)
return dataSubmitted
}
And i have the other model is called "profile" for user profile. I use user._id to releation with "profile" model.
My profile model:
module.exports = (mongoose, mongoosePaginate) => {
const schema = mongoose.Schema({
name: String,
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
}, {
timestamps: true
})
schema.plugin(mongoosePaginate)
const profile = mongoose.model('profile', schema)
return profile
}
The result json from select dataSubmitted, is like this:
totalItems": 90,
"data": [
{
"_id": "63546cb05bfb8607c005da6a",
"user": "6353a1aebaf28d7aa066a963",
"company": "6022487bbe148f3a9b132122",
"createdAt": "2022-10-22T22:20:32.296Z",
"updatedAt": "2022-10-25T07:09:52.363Z",
"__v": 0
},
]
My question is how can i populate the user id with "profile" model?
My current code:
const options = {
populate: [
{
path: 'user',
populate: {
path: 'user',
model: 'profile'
}
}
],
sort: ({ createdAt: -1 })
}
but its return "user": null if i add nested populate like that.

If you need to reference the profile model from the dataSubmitted you should change your schema declaration to:
const dataSubmittedSchema = mongoose.Schema(
{
profile: {
type: mongoose.Schema.Types.ObjectId,
ref: 'profile',
},
company: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
},
{
timestamps: true,
}
);
Then, you should be able to populate with:
dataSubmitted.find({}).populate({
path: 'profile',
populate: {
path: 'user'
}
})

Related

How to push items in to an array which was referenced in collections schema in mongoose, nodejs

i want to create an item and push it into items array which was referenced in my collections schema. What i am sending in the payload is item properties and collection id. But i am getting CastError. Please help
COLLECTION SCHEMA
const collectionSchema = new Schema(
{
name: { type: String },
description: { type: String },
owner: { type: Schema.Types.ObjectId, ref: "User" },
items: [{ type: Schema.Types.ObjectId, require: true, ref: "Item" }],
},
{ timestamps: true }
);
export default model("Collection", collectionSchema);
ITEM SCHEMA
import mongoose from "mongoose";
const { Schema, model } = mongoose;
const itemSchema = new Schema(
{
name: { type: String },
description: { type: String },
owner: { type: Schema.Types.ObjectId, ref: "User" },
likes: [{ type: Schema.Types.ObjectId, ref: "User" }],
collections: { type: Schema.Types.ObjectId, ref: "Collection" },
},
{ timestamps: true }
);
export default model("Item", itemSchema);
CREATE ITEM ROUTE
itemRouter.post("/", JWTAuthMiddleware, async (req, res, next) => {
const item = new ItemModal(req.body)
const collection = await CollectionModal.findByIdAndUpdate(
req.user._id,
{
$push : { items: [{ ...req.body, id: item._id }] },
},
{ new: true }
);
res.send(collection);
});
What i am getting is an CASTERROR

Mongo aggregate $match and $group in $lookup result

I have node text
I have 3 models lead, user and company
I want to get all customers for selected company id using lead model
what I try was,
using $lookup and $group I got unique customer with details but after adding $match I got empty array
I hope someone can get my on the right track..
****This is my Aggregation code ****
const customers = await Lead.aggregate([
{
$match: { moving_company: companyId },
},
{
$group: {
_id: {
"customer": "$customer",
},
}
},
{
$lookup: {
from: "users",
localField: "_id.customer",
foreignField: "_id",
as: "myCustomResut",
},
},
]);
This is my Company model
const schemaOptions: mongoose.SchemaOptions = {
_id: true,
id: false,
timestamps: true,
skipVersioning: true,
strict: false,
toJSON: {
getters: true,
virtuals: true,
},
};
export const CompanySchema = new mongoose.Schema(
{
name: {
type: Schema.Types.String,
},
},
schemaOptions
);
const Company = mongoose.model<ICompany>("Company", CompanySchema);
export default Company;
This my lead model
const schemaOptions: mongoose.SchemaOptions = {
_id: true,
id: false,
timestamps: true,
skipVersioning: true,
strict: false,
toJSON: {
getters: true,
virtuals: true,
},
};
export const LeadSchema = new mongoose.Schema(
{
status: {
type: Schema.Types.String,
},
customer: {
type: Schema.Types.ObjectId,
ref: Customer.modelName
},
assigned_sales_agent: {
type: Schema.Types.String,
ref: Agent.modelName
},
moving_company: {
type: Schema.Types.ObjectId,
ref:Company.modelName
},
selected_categories: [
{
type: SelectedCategorySchema,
},
],
},
schemaOptions
);
const Lead = mongoose.model<ILead>("Lead", LeadSchema);
export default Lead;
This is my customer model
export const customerSchema = new mongoose.Schema(
{
address: {
type: Schema.Types.ObjectId,
ref: Addresses,
},
},
UserSchemaOptions
);
export const Customer = User.discriminator<ICustomer>(
"Customer",
customerSchema,
Role.CUSTOMER
);
export default Customer;

Mongoose .populate() does not populate

I have two schema's Role and User. When I do a Role.find() I want to populate the users with the users that have that specific role.
let roleSchema = new Schema({
name: {
type: String,
required: true,
},
...,
users: [{
type: mongoose.Schema.ObjectId,
ref: 'User'
}]
}, {
timestamps: true,
});
const Role = mongoose.model('Role', roleSchema);
let userSchema = new Schema({
username: {
type: String,
required: true,
},
...,
role: {
type: mongoose.Schema.ObjectId,
ref: 'Role'
},
}, {
timestamps: true,
}
);
const User = mongoose.model('User', userSchema);
When I get the Role with the following code:
Role.findById(req.params.roleId)
.populate('users')
.then(role => {
res.send(role);
}).catch(err => {
res.send(err)
});
It returns the following:
{
"users": [
],
"_id":"5c78006df35ca926534ad865",
"name":"Role",
"createdAt":"2019-02-28T15:38:21.741Z",
"updatedAt":"2019-02-28T15:38:21.741Z",
"__v":0
}
User.find().populate('role') works just fine, but Role.find().populate('users') doesn't.
Am I doing something wrong or don't I need .populate() in this case?
Nevermind. I think I had to use aggregate().lookup() for that all along... since there weren't any ids in Role.users...
Role.aggregate()
.lookup({
from: 'users',
localField: '_id',
foreignField: 'role',
as: 'users'
}).then( role => {
res.send(role);
});
This gave me the response I wanted.

Populate() Mongoose is not returning joined data

Well, I´am trying to retrieve Name and Lastname from user who created the document but it´s not working, it still returning Mongo´s Id
This is my areas model
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var model = new Schema({
NAME: { type: String, required: true, unique: true, max: 50, min: 3 },
STATUS: { type: String, default: 'active' },
ADDED_BY: { type: Schema.Types.ObjectId, ref: 'users' },
ADDED_DATE: { type: Date, default: Date.now }
}, {collection :'areas'})
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('Area', model )
This is the user model
var mongo = require('mongoose'),
validator = require('mongoose-unique-validator'),
Schema = mongo.Schema
var userSchema = new Schema({
PERSONAL_DATA: {
NAME: { type: String, required: [ true, 'The name is necessary' ], max: 50 },
LAST_NAME: { type: String, required: [ true, 'the lastname is necessary' ], max: 100 },
PHOTO: { type: String, max: 100 },
BIRTHDAY: { type: Date },
MARITIAL_STATUS: { type: Schema.Types.ObjectId, ref: 'maritial_statuses' },
GENDER: { type: String, max: 1 },
EMAIL: { type: String, required: true },
},
COMPANY_DATA: {
JOB: { type: Schema.Types.ObjectId, ref: 'jobs' },
AREA: { type: Schema.Types.ObjectId, ref: 'areas' },
ROLE: { type: Schema.Types.ObjectId, ref: 'roles' },
BOSS: { type: Schema.Types.ObjectId, ref: 'users' },
}
}, { collection: 'users' } )
model.plugin( validator, { message: 'The {PATH} is not valid or duplicated' } )
module.exports = mongo.model('User', userSchema )
And this is my areas route
var express = require('express'),
model = require('../../models/catalogs/areas'),
app = express()
app.get('/:from', (req, res) => {
var from = parseInt( req.params.from )
model.find()
.sort('NAME').populate({ path: 'users', select: 'NAME LAST_NAME'})
.limit(10).skip(from)
.exec((error, data) => {
if (error) {
return res.status(500).json({
success: false,
error
})
}
res.status(200).json({
success: true,
data
})
})
})
module.exports = app
The response is
{
"success": true,
"data": [
{
"STATUS": "active",
"_id": "5c547f4adadf433914f72c8c",
"NAME": "Contabilidad y Finanzas",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-01T17:18:02.680Z",
"__v": 0
},
{
"STATUS": "active",
"_id": "5c547f3edadf433914f72c8b",
"NAME": "Tecnologías",
"ADDED_BY": "5c4f562deec6f4defeea759b",
"ADDED_DATE": "2019-02-01T17:17:50.579Z",
"__v": 0
}
]
}
As you seen, ADDED_BY is a field joined to Users and I want to retrieve that information. I don´t know what is wrong with my code.

Trying to populate an object inside another object that is inside another object (NODE.JS)

This function gets a specific "process" and shows the following information in json: (POSTMAN)
{
"process": {
"_id": "5c18e8d1d4817811839d43d2",
"name": "Dyeing",
"colour": {
"_id": "5c18c972b39bb20769288e8f",
"name": "azul",
"category": "5c18c09f4c6baf05ea621bca",
"__v": 0
},
"__v": 0
},
"request": {
"type": "GET",
"url": "http://localhost:3000/process"
}
}
Process controller function
exports.process_get_process = (req, res, next) => {
Process.findById(req.params.processId)
.populate("colour")
.populate("category")
.exec()
.then(process => {
if (!process) {
return res.status(404).json({
message: "Process not found"
});
}
res.status(200).json({
process: process,
request: {
type: "GET",
url: "http://localhost:3000/process"
}
});
})
.catch(err => {
res.status(500).json({
error: err
});
});
};
The model for the "process" is the following schema:
const mongoose = require('mongoose');
const processSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
price: { type: Number, required: false },
colour: { type: mongoose.Schema.Types.ObjectId, ref: 'Colour', required: false },
});
module.exports = mongoose.model('Process', processSchema);
This is the Colour model:
As you can see the object "category" is inside "colour" and i want to show him in the "process" object as well.
const mongoose = require('mongoose');
const colourSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: { type: String, required: true },
category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
});
module.exports = mongoose.model('Colour', colourSchema);
Problem: Inside the "colour" exist a "category" object, but only shows the category id, and i want him to show all the category information. How can I populate it?
You can specify that as options for the populate function.
Process.findById(req.params.processId)
.populate({
path: 'colour',
populate: { path: 'category' }
})
.exec()

Resources