Populate() Mongoose is not returning joined data - node.js

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.

Related

One to many with MongoDB (Mongoose) with .populate()

What I am doing
I am trying to return a player by playerId with all ref items from each object in it's schema. In this example, I am specifically talking about the players inventory.
How can I return all reference items and their properties?
In my service file, I am getting my player with:
/**
* Get a player by playerId
* #param playerId
* #returns {Promise<*>}
*/
module.exports.getPlayer = async (playerId) => {
return await Player.findOne({ playerId: playerId }).populate('inventory');
};
And this is my returned JSON
{
"success": true,
"data": {
"_id": "63bb1f3ec17d33f4d2a87194",
"playerId": 4183489039,
"name": "AlanGreyjoy",
"currency": {
"copper": 500,
"silver": 10,
"gold": 0
},
"online": false,
"inventory": [
{
"currentDurability": 0,
"item": "63ba0c54407456969ba38615",
"amount": 1,
"_id": "63bc4fa070eaa247288e3573",
"createdAt": "2023-01-09T17:32:16.643Z",
"updatedAt": "2023-01-09T17:32:16.643Z"
}
],
"bank": [],
"questTracker": [],
"friends": [],
"knownRecipes": [],
"jobs": [],
"createdAt": "2023-01-08T19:53:34.903Z",
"updatedAt": "2023-01-09T17:32:16.643Z",
"__v": 1
}
}
As you can see, the item in the inventory array is not populating with the ref item from the items collection.
I have googled and googled and tried so many different things, but nothing is working.\
The item does exist in the db
My Models
My Player.model.js
const mongoose = require('mongoose');
const toJSON = require('../plugins/mongoToJson');
const Schema = mongoose.Schema;
const questTracker = new Schema(
{
quest: { type: mongoose.Schema.Types.ObjectId, ref: 'Quest' },
complete: { type: Boolean, default: false },
},
{ timestamps: true }
);
const friends = new Schema(
{
player: { type: mongoose.Schema.Types.ObjectId, ref: 'Player' },
isFavorite: { type: Boolean, default: false },
},
{ timestamps: true }
);
const knownRecipes = new Schema(
{
recipe: { type: mongoose.Schema.Types.ObjectId, ref: 'Recipe' },
},
{ timestamps: true }
);
const jobs = new Schema(
{
job: { type: mongoose.Schema.Types.ObjectId, ref: 'Job' },
},
{ timestamps: true }
);
const inventoryItems = new Schema(
{
item: { type: mongoose.Schema.Types.ObjectId, ref: 'Item' },
amount: { type: Number, default: 0 },
currentDurability: { type: Number, default: 0 },
},
{ timestamps: true }
);
const bank = new Schema(
{
item: { type: mongoose.Schema.Types.ObjectId, ref: 'Item' },
amount: { type: Number, default: 0 },
},
{ timestamps: true }
);
const playerSchema = new Schema(
{
playerId: {
type: Number,
unique: true,
required: true,
},
name: {
type: String,
required: true,
unique: true,
},
currency: {
type: Object,
default: {
copper: 500,
silver: 10,
gold: 0,
},
},
inventory: [inventoryItems],
bank: [bank],
questTracker: [questTracker],
friends: [friends],
knownRecipes: [knownRecipes],
jobs: [jobs],
online: {
type: Boolean,
default: false,
},
},
{ timestamps: true }
);
const PlayerModel = mongoose.model('player', playerSchema);
module.exports = PlayerModel;
My Item.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const toJSON = require('../plugins/mongoToJson');
const vendorPriceSchema = mongoose.Schema({
copper: {
type: Number,
default: 0,
},
silver: {
type: Number,
default: 0,
},
gold: {
type: Number,
default: 0,
},
});
const itemSchema = new Schema(
{
title: {
type: String,
required: true,
unique: true,
},
assetId: {
type: Number,
required: true,
},
description: {
type: String,
},
equipDescription: {
type: String,
},
additionalDescription: {
type: String,
},
consumableUseDescription: {
type: String,
},
itemLevel: {
type: Number,
},
requiredLevel: {
type: Number,
},
type: {
type: String,
required: true,
},
subtype: {
type: String,
required: true,
},
stamina: {
type: Number,
},
intellect: {
type: Number,
},
criticalStrike: {
type: Number,
},
agility: {
type: Number,
},
mastery: {
type: Number,
},
maxDurability: {
type: Number,
},
vendorPrice: { vendorPriceSchema },
minDamage: {
type: Number,
default: 0,
},
maxDamage: {
type: Number,
default: 0,
},
speed: {
type: Number,
},
maxStack: {
type: Number,
},
},
{ timestamps: true }
);
const ItemModel = mongoose.model('Item', itemSchema);
module.exports = ItemModel;
You can use something like this:
module.exports.getPlayer = async (playerId) => {
return await Player.findOne({ playerId: playerId }).populate({
path: "inventory",
populate: {
path: "item",
},
});
};

Joining two mongoose collections with many to many relationship

I have two models which are Product & Category with many to many relationship.
Following are my models
This is the model for Product
//Product.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const { ObjectId } = Schema;
const product = {
name: {
type: String,
required: true,
trim: true,
minlength: [2, "Too short"],
maxlength: [32, "Too long"],
unique: true,
},
slug: {
type: String,
unique: true,
lowercase: true,
index: true,
},
category: [
{
type: ObjectId,
ref: "Category",
},
],
description: {
type: String,
maxlength: 200,
},
price: {
type: Number,
required: true,
trim: true,
maxlength: 32,
},
shipping: {
type: String,
enum: ["Yes", "No"],
},
color: [
{
type: String,
enum: ["Black", "Brown", "Silver", "White", "Blue"],
},
],
sold: {
type: Number,
default: 0,
},
quantity: {
type: Number,
},
images: [
{
public_id: String,
url: String,
},
],
};
const productSchema = new Schema(product, { timestamps: true });
const Product = mongoose.model("Product", productSchema);
module.exports = Product;
This is the model for Category
//Category.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const { ObjectId } = Schema;
const category = {
name: {
type: String,
required: true,
trim: true,
max: 32,
unique: true,
},
subCategories: [
{
type: Schema.Types.ObjectId,
ref: "Category",
},
],
parent: {
type: Schema.Types.ObjectId,
ref: "Category",
},
products: [
{
type: ObjectId,
ref: "Product",
},
],
slug: {
type: String,
required: "URL can't be empty",
unique: true,
},
};
const categorySchema = new Schema(category, { timestamps: true });
//Validate the slug to ensure proper url is given
// categorySchema.path("slug").validate((val) => {
// urlRegex =
// /(ftp|http|https):\/\/(\w+:{0,1}\w*#)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%#!\-/]))?/;
// return urlRegex.test(val);
// }, "Invalid URL.");
const autoPopulateChildren = function (next) {
this.populate("subCategories");
// this.populate("parent");
next();
};
categorySchema
.pre("findOne", autoPopulateChildren)
.pre("findById", autoPopulateChildren)
.pre("find", autoPopulateChildren);
const Category = mongoose.model("Category", categorySchema);
module.exports = Category;
So, product has a foreign keys of category in array of category. Whereas Category has foreign keys of product in array of products. How do you join them ?
I tried this & it doesn't work. It returns empty object
router.get("/products", [RequireSignIn], async (req, res) => {
try {
const products = await Product.find({}).aggregate({
$lookup: {
from: "Category",
localField: "category",
foreignField: "_id",
as: "ProductCategories",
},
});
return res.status(200).send(products);
} catch (error) {
return res.status(200).send(error);
}
});

How to get model data from nested object

little bit stuck with mongoose. I want to get all users projects where he's added. Tried few options, but in all of them I receive an empty array. So the main question is it possible somehow to find all project by filtering/finding the Project model?
This is how looks my default response to understand what I'm looking for:
{
"_id": "61a8bc4e8e24f10ac7a7288d",
"name": "Random project",
"description": "Random project desc",
"maxWorkingEmployees": 5,
"status": "Paused",
"createdBy": {
"_id": "61a66578f2dabf7555bcf4ab",
"email": "Henrikas#furniture1.eu",
"role": "Owner"
},
"currentlyWorkingEmployees": [
{
"username": "Ema",
"role": "Employee",
"_id": "61a8e0423140ecce769dc971"
}
],
"createdAt": "2021-12-02T12:30:06.461Z",
"updatedAt": "2021-12-02T15:11:51.361Z",
"__v": 0
}
Project model:
const mongoose = require('mongoose');
const SingleUserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
role: {
type: String,
required: true,
},
});
const ProjectSchema = new mongoose.Schema(
{
name: {
type: String,
required: [true, 'Provide project name'],
minlength: 5,
},
description: {
type: String,
required: [true, 'Provide description about the project'],
},
maxWorkingEmployees: {
type: Number,
required: [
true,
'Provide maximum number of employees working on this project',
],
},
currentlyWorkingEmployees: [SingleUserSchema],
status: {
type: String,
enum: ['Pending', 'In progress', 'Paused', 'Delayed', 'Completed'],
default: 'Pending',
},
createdBy: {
type: mongoose.Schema.ObjectId,
ref: 'User',
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model('Project', ProjectSchema);
Here's my controller and my first try:
const getMyProjects = async (req, res) => {
const userId = req.user.userId;
const projects = await Project.find({
currentlyWorkingEmployees: { _id: userId },
});
res.json({projects});
};
Second shot after reading some articles
const getMyProjects = async (req, res) => {
const userId = req.user.userId;
const projects = await Project.aggregate([
{
$match: {
currentlyWorkingEmployees: { _id: userId },
},
},
]);
};
As I said in the comment you can do it accessing to the internal object of the schema with an string accessing to it child object.
Project.find({'currentlyWorkingEmployees._id': userId})

Mongo populate not working and not retrieve data model

I have a problem in populate method in mongodb it can't retrieve data from model. Can anyone help me solve that problem?
This is the code
router.get('/', auth, async (req, res) => {
try {
const user = req.user._id;
const wishlist = await Wishlist.find({ user, isLiked: true })
.populate({
path: 'Products',
select: 'title',
})
.sort('-updated');
res.status(200).json({
wishlist,
});
} catch (error) {
res.status(400).json({
error: 'Your request could not be processed. Please try again.',
});
}
});
When I navigate to http://localhost:3000/wishlist/, this is the response I get:
{
"wishlist": [
{
"product": "60cb5eb82cc7091ae2e31c88",
"user": "60cb6c46291247466fe08f92",
"isLiked": true,
"_id": "60d1a656567e08bf89571209",
"updated": "2021-06-22T10:09:25.295Z",
"created": "2021-06-22T08:59:02.434Z",
"__v": 0
}
]
}
The model of products
const mongoose = require('mongoose');
const { Schema } = mongoose;
const ProductSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
category:{
type: Schema.Types.ObjectId,
ref: 'Categories',
default: null
},
photo: { type: String, required: true },
createdAt: {
type: Date,
default: new Date(),
},
updateAt: Date,
price: {
type: String,
required: true,
},
quantity: {
type: Number
}
,
isActive: {
type: Boolean,
default: true
},
user: {
type: Schema.Types.ObjectId,
ref: "User",
}
});
module.exports = mongoose.model('Product', ProductSchema);
The model for wishlist:
const Mongoose = require('mongoose');
const { Schema } = Mongoose;
// Wishlist Schema
const WishlistSchema = new Schema({
product: {
type: Schema.Types.ObjectId,
ref: 'Product',
default: null,
},
user: {
type: Schema.Types.ObjectId,
ref: 'User',
default: null,
},
isLiked: {
type: Boolean,
},
updated: {
type: Date,
default: Date.now,
},
created: {
type: Date,
default: Date.now,
},
});
module.exports = Mongoose.model('Wishlist', WishlistSchema);
Can anyone help me please to find the solution for that problem?

Mongoose won't populate an array or object

Im having an issue where i have a Fixtures schema like so:
const FixtureSchema = mongoose.Schema({
home: {
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'club'
},
score: {
type: Number,
default: 0
},
scorers: [
{
player: {
type: mongoose.Schema.Types.ObjectId,
ref: 'player'
}
}
]
},
away: {
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'club'
},
score: {
type: Number,
default: 0
},
scorers: [
{
player: {
type: mongoose.Schema.Types.ObjectId,
ref: 'player'
}
}
]
},
match_num: {
type: Number,
required: true
},
date: {
type: Date,
default: Date.now()
}
});
module.exports = Fixture = mongoose.model('fixture', FixtureSchema);
Club schema:
const ClubSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
});
module.exports = Club = mongoose.model('club', ClubSchema);
Player Schema:
const PlayerSchema = new mongoose.Schema({
name: {
type: String,
require: true
},
club: {
type: mongoose.Schema.Types.ObjectId,
ref: 'club'
},
stats: {
starts: {
type: Number,
default: 0
},
goals: {
type: Number,
default: 0
},
assists: {
type: Number,
default: 0
},
goal_streak: {
type: Number,
default: 0
}
}
});
module.exports = Player = mongoose.model('player', PlayerSchema);
I make a request like this:
router.get('/', async (req, res) => {
try {
const fixture = await Fixture.find()
.populate('player', ['name'])
.populate('club', ['name']);
res.json(fixture);
} catch (err) {
console.error(err.message);
}
});
Postman get request gives me:
[
{
"home": {
"score": 1,
"club": "5e3dfcffb52ec61c30fc44cd",
"scorers": [
{
"_id": "5e4aac5d81d92b368398bd4d",
"player": "5e3dfddd4884f51cb7ee61e9"
}
]
},
"away": {
"score": 0,
"club": "5e3dfd18b52ec61c30fc44ce",
"scorers": []
},
"date": "2020-02-17T15:07:57.229Z",
"_id": "5e4aac5d81d92b368398bd4c",
"match_num": 1,
"__v": 0
}
]
Why is it not populating the name of the player or the club??? It works when it is not stored in an array or object.. Ive tried looking for advice on other topics but cant find anything relating to this..
Thanks for any replies and advice
Turns out it was the same as the other questions!!! lol..
If i change :
.populate('club', ['name']);
to
.populate('home.club', ['name']);
and so on
it solves it...

Resources