I am trying to use mongodb query .populate() to populate user data in my allocations response.
But i looks like it is not working. It is not populating user data but only id (take a look at response below). I have tride to use "user" or "users" but when i use "user" it return user as null
User model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
allocations: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'allocation'
}],
admin: {
type: Boolean,
default: false
},
date: {
type: Date,
default: Date.now
},
});
module.exports = mongoose.model('users', UserSchema);
Allocations models
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const AllocationSchema = new Schema({
name: {
type: String,
default: 'New'
},
jan: {
type: String,
default: 0
},
feb: {
type: String,
default: 0
},
mar: {
type: String,
default: 0
},
apr: {
type: String,
default: 0
},
may: {
type: String,
default: 0
},
jun: {
type: String,
default: 0
},
jul: {
type: String,
default: 0
},
aug: {
type: String,
default: 0
},
sep: {
type: String,
default: 0
},
nov: {
type: String,
default: 0
},
oct: {
type: String,
default: 0
},
dec: {
type: String,
default: 0
},
})
const AllocationsSchema = new Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
refs: 'users'
},
year: {
type: String,
},
allocations: [AllocationSchema],
date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('allocation', AllocationsSchema);
exports.getAllUsersAndAllocations = async (req, res) => {
try {
let users = await AllocationModel.find({
year: "2019"
}).populate(
'user'
)
return res.json(users)
} catch (error) {
console.error(error.message)
return res.status(500).send('Server error')
}
}
response:
{
"_id": "5d76ceb0e1fa5c2b6f8f5bed",
"user": "5d7671c446c7ba228ca1382b",
"year": "2019",
"allocations": [
{
"name": "New",
"jan": "0",
"feb": "0",
"mar": "0",
"apr": "0",
"may": "0",
"jun": "0",
"jul": "0",
"aug": "0",
"sep": "0",
"nov": "0",
"oct": "0",
"dec": "0",
"_id": "5d76ceb3e1fa5c2b6f8f5bef"
},
{
"name": "New",
"jan": "0",
"feb": "0",
"mar": "0",
"apr": "0",
"may": "0",
"jun": "0",
"jul": "0",
"aug": "0",
"sep": "0",
"nov": "0",
"oct": "0",
"dec": "0",
"_id": "5d76ceb0e1fa5c2b6f8f5bee"
}
],
"date": "2019-09-09T22:14:08.573Z",
"__v": 1
},
It looks like it may just be a typo in your AllocationSchema. Under 'User' you have written refs: 'users' when it should be ref: 'users' i.e. 'ref' instead of 'refs'
Related
This are my schemas
var employeesSchema = new schema({
companyName: { type: String },
employeeName: { type: String },
employeeCode: { type: String, unique: true },
designation: { type: String },
department: { type: String },
officeLocation: { type: String },
workLocation: { type: String },
emailID: { type: String , unique: true},
managerName: { type: String },
managerEmail: { type: String },
countryCode: { type: String },
mobile: { type: String },
password: { type: String },
createdDate: { type: Date, default: new Date() }
})
var leaveRequests = new schema({
leaveRequestID: { type: String, unique: true },
employeeCode: { type: String, required: true },
requestedBy: { type: mongoose.Schema.Types.ObjectId, ref: "employees_master", required: true },
leaveType: { type: mongoose.Schema.Types.ObjectId, ref: "leavetypes", required: true },
startDate: { type: Date },
endDate: { type: Date },
remarks: { type: String },
documentUrl: { type: String },
status: { type: String, enum: ['pending', 'rejected', 'approved'], default: 'pending' },
statusUpdatedBy: { type: mongoose.Schema.Types.ObjectId, ref: "manager_or_lead_master" },
reason: { type: String },
isActive: { type: Boolean, default: true },
createdDate: { type: Date, default: new Date() },
});
Im trying to filter data with managerEmail: req.body.emailID
exports.getTeamLevelLeaveRequest = async (req, res) => {
try {
const getQuery = leaverequests.find({})
.populate('leaveType')
.populate('statusUpdatedBy')
.populate({
path: 'requestedBy',
match: {
managerEmail: req.body.emailID
}
})
.sort({ _id: -1 })
const resp = await getQuery;
const resAfterMap = resp.filter(u => u.requestedBy !== null)
responseHandler.successResponse(res, resAfterMap, "Leave Requests")
} catch (err) {
responseHandler.errorResponse(res, err, commonErrorMessage)
}
}
But Im receiving resp like
[{
"_id": "634e7459f78e446637a70ac6",
"leaveRequestID": "LR10",
"employeeCode": "MLI637",
"requestedBy": null,
"leaveType": {
"_id": "634d8d7ab69f5a80c4c98216",
"leaveType": "Compensatory Off",
"__v": 0,
"name": "Compensatory Off"
},
"startDate": "2022-10-18T18:30:00.000Z",
"endDate": "2022-10-18T18:30:00.000Z",
"remarks": "test",
"status": "pending",
"isActive": true,
"createdDate": "2022-10-18T08:27:42.042Z",
"__v": 0
},
{
"_id": "634e719c71313319a6da2432",
"leaveRequestID": "LR9",
"employeeCode": "MLI699",
"requestedBy": null,
"leaveType": {
"_id": "634d8d7ab69f5a80c4c98216",
"leaveType": "Compensatory Off",
"__v": 0,
"name": "Compensatory Off"
},
"startDate": "2022-10-18T18:30:00.000Z",
"endDate": "2022-10-18T18:30:00.000Z",
"remarks": "test",
"status": "pending",
"isActive": true,
"createdDate": "2022-10-18T08:25:04.220Z",
"__v": 0
},
{
"_id": "634e719c71313319a6da2432",
"leaveRequestID": "LR9",
"employeeCode": "MLI699",
"requestedBy": {
**populated data came ----**
},
"leaveType": {
"_id": "634d8d7ab69f5a80c4c98216",
"leaveType": "Compensatory Off",
"__v": 0,
"name": "Compensatory Off"
},
"startDate": "2022-10-18T18:30:00.000Z",
"endDate": "2022-10-18T18:30:00.000Z",
"remarks": "test",
"status": "pending",
"isActive": true,
"createdDate": "2022-10-18T08:25:04.220Z",
"__v": 0
},
]
I want to get data without filtering requestedBy is not equal to null
Im using filter method to do.
Is there any option to find filter data....
Hello I want to return recent 5 documents with only pickup objects with distinct values of pickup.loc in it.
Here is my schema:
const schema = new Schema<IShipment>({
shipper: { type: Schema.Types.ObjectId, ref: "USER" },
pickup: {
loc: { type: String, required: true }, // pickup address
date: { type: Date, default: new Date() },
time: {
from: { type: String },
to: { type: String },
},
latlng: {
type: { type: String, enum: [ "Point", "LineString", "Polygon" ], default: "Point" },
coordinates: { type: [Number], index: "2dsphere" }
},
person: {
name: { type: String },
phone: { type: String },
},
companyName: { type: String, required: true },
zip: { type: String, required: true },
}
}
Currently I m just getting recent 5 documents with pickup objects in it. Here is my query:
const select = { "pickup.companyName": 1, "pickup.loc": 1, "pickup.person": 1, "pickup.zip": 1, _id: 0 };
ShipmentModel.find({ shipper: userId }, select).sort({ $natural: -1 }).limit(5)
How can I get distinct values of pickup.loc and return recent documents with pickup objects? I m attaching the required response with comments in it
required response
[
{
"person": {
"name": "Ali",
"phone": "123456789"
},
"loc": "ELA Logistics pickup4, Uthal, 90150", //should be distinct
"companyName": "ELA Logistics pickup4",
"zip": "90150"
},
{
"person": {
"name": "Ali",
"phone": "123456789"
},
"loc": "ELA Logistics pickup4, Uthal, 90150", //should be distinct
"companyName": "ELA Logistics pickup4",
"zip": "90150"
},
]
In my Node API and MongoDB, I'm trying to make an endpoint to get all the posts associated with one username of a profile. In my Profile schema, I have a reference to the Post Schema and in my Post schema, I have a reference to the Username from Profile schema.
My issue I don't know how to get all the posts for that username. I did similarly but with embedded for the Experience schema but I'm not sure how to do that for the referenced collections.
Post model:
const { Connect } = require("../db");
const reactionSchema = {
likedBy: {
type: String,
unique: true,
sparse: true
}
};
const postSchema = {
text: {
type: String,
required: true,
unique: true,
sparse: false
},
username: {
type: Connect.Schema.Types.String,
ref: "Profile"
},
image: {
type: String,
default: "https://via.placeholder.com/150",
required: false
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
reactions: [reactionSchema],
comments: {
type: Connect.Schema.Types.ObjectId,
ref: "Comment",
required: false
}
};
const collectionName = "post";
const postSchemaModel = Connect.Schema(postSchema);
const Post = Connect.model(collectionName, postSchemaModel);
module.exports = Post;
Profile model:
// Here defining profile model
// Embedded we have the Experience as []
const { Connect } = require("../db");
const { isEmail } = require("validator");
const postSchema = {
type: Connect.Schema.Types.ObjectId,
ref: "Post"
};
const experienceSchema = {
role: {
type: String,
required: true
},
company: {
type: String,
required: true
},
startDate: {
type: Date,
required: true
},
endDate: {
type: Date,
required: false
},
description: {
type: String,
required: false
},
area: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
username: {
type: String,
required: false
},
image: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
}
};
const profileSchema = {
firstname: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
email: {
type: String,
trim: true,
lowercase: true,
unique: true,
required: [true, "Email is required"],
validate: {
validator: string => isEmail(string),
message: "Provided email is invalid"
}
},
bio: {
type: String,
required: true
},
title: {
type: String,
required: true
},
area: {
type: String,
required: true
},
imageUrl: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
},
username: {
type: String,
required: true,
unique: true
},
experience: [experienceSchema],
posts: [postSchema],
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
}
};
const collectionName = "profile";
const profileSchemaModel = Connect.Schema(profileSchema);
const Profile = Connect.model(collectionName, profileSchemaModel);
module.exports = Profile;
I was able to make this for the embedded experience but not sure that correct for referenced collection:
const profileWithExperiences = await Student.aggregate([
{ $match: { username: res.username.username } },
{
$unwind: "$experience"
},
{
$match: {
"experience._id": new ObjectID(req.params.experienceId)
}
},
{
$project: {
username: 1,
experience: 1,
_id: 0
}
}
]);
I would like to see an example for referenced collections as it is confusing me how should I do that
[EDIT]
JSON for Profiles and Posts
{
"_id": ObjectId("5e2c98fc3d785252ce5b5693"),
"imageUrl": "https://i.pravatar.cc/300",
"firstname": "Jakos",
"surname": "Lemi",
"email": "lemi#email.com",
"bio": "My bio bio",
"title": "Senior IT developer",
"area": "Copenhagen",
"username": "Jakos",
"experience": [
{
"image": "https://via.placeholder.com/150",
"_id": ObjectId("5e3975f95fbeec9095ff3d2f"),
"role": "Developer",
"company": "Google",
"startDate": ISODate("2018-11-09T23:00:00.000Z"),
"endDate": ISODate("2019-01-05T23:00:00.000Z"),
"area": "Copenhagen",
"createdAt": ISODate("2020-02-04T13:47:37.167Z"),
"updatedAt": ISODate("2020-02-04T13:47:37.167Z")
},
{
"image": "https://via.placeholder.com/150",
"_id": ObjectId("5e3978bf5e399698e20c56d4"),
"role": "Developer",
"company": "IBM",
"startDate": ISODate("2018-11-09T23:00:00.000Z"),
"endDate": ISODate("2019-01-05T23:00:00.000Z"),
"area": "Copenhagen",
"createdAt": ISODate("2020-02-04T13:59:27.412Z"),
"updatedAt": ISODate("2020-02-04T13:59:27.412Z")
}
],
"createdAt": ISODate("2020-01-25T19:37:32.727Z"),
"updatedAt": ISODate("2020-02-04T23:14:37.122Z"),
"__v": NumberInt("0")
}
Post
{
"_id": ObjectId("5e3beb639e072afedd19dcef"),
"username": ObjectId("5e2c98fc3d785252ce5b5693"),
"image": "https://via.placeholder.com/150",
"text": "My awesome post",
"createdAt": ISODate("2020-02-06T10:33:07.22Z"),
"updatedAt": ISODate("2020-02-06T10:33:07.22Z"),
"reactions": [ ],
"__v": NumberInt("0")
}
Output expected:
{
"username": "Jakos",
"postsCount": [1],
"posts": [
{
"_id": ObjectId("5e3beb639e072afedd19dcef"),
"image": "https://via.placeholder.com/150",
"text": "My awesome post",
"createdAt": ISODate("2020-02-06T10:33:07.22Z"),
"updatedAt": ISODate("2020-02-06T10:33:07.22Z"),
"reactions": [ ],
"__v": NumberInt("0")
}
]
}
I want to see all the posts related to that username
You can use the $lookup aggregation to join collections.
db.profiles.aggregate([
{
$match: {
username: "Jakos"
}
},
{
$lookup: {
from: "posts", //the name of the posts collection, change this if it is different
localField: "_id",
foreignField: "username",
as: "posts"
}
},
{
$project: {
username: 1,
posts: 1,
postsCount: {
$size: "$posts"
},
_id: 0
}
}
])
Playground
For mongoose it should be like this in your app:
const profileWithExperiences = await Student.aggregate([
{ $match: { username: res.username.username } },
{
$unwind: "$experience"
},
{
$lookup: {
from: "posts", //the name of the posts collection, change this if it is different
localField: "_id",
foreignField: "username",
as: "posts"
}
},
{
$project: {
username: 1,
posts: 1,
postsCount: {
$size: "$posts"
},
_id: 0
}
}
]);
Try to get like this i am getting data from two table with the use of node and mongodb.
var param = {};
param['user_id']=id;
var search={ user_id:param.user_id,status: [ 'Pending', 'Accepted' ] };
var output={};
output = await JobRequest.find(search);
if(output !=0)
{
var JSon=await JobRequest.aggregate([
{$match: { user_id: {$gte:id}} },
{
"$project": {
"employee_id": {
"$toObjectId": "$employee_id"
},
"service_id": {
"$toObjectId": "$service_id"
},
"createdDate": {
"$toString": "$createdDate"
},
"chat_status": {
"$toString": "$chat_status"
},
"status": {
"$toString": "$status"
},
"delivery_address": {
"$toString": "$delivery_address"
},
"delivery_lat": {
"$toString": "$delivery_lat"
},
"delivery_lang": {
"$toString": "$delivery_lang"
},
}
},
{
$lookup:
{
from: "employees",
localField: "employee_id",
foreignField: "_id",
as: "employee_details"
}
},
{
$lookup:
{
from: "services",
localField: "service_id",
foreignField: "_id",
as: "service_details"
}
}
]);
My profile document is saved in my DB as the following:
{
"_id": {
"$oid": "5c3aa1de18ad682fb1444138"
},
"user": {
"$oid": "5c318f56e3224b15e0fdbd06"
},
"company": {
"info": {
"$oid": "5c318f56e3224b15e0fdbd07"
},
"position": "Stemuli"
},
"hometown": "Dallas",
"date": {
"$date": "2019-01-13T02:26:38.185Z"
},
"__v": 0
}
I am trying to populate the field company.info within the newly saved Profile.
new Profile(profileFields).save().then(profile => {
Profile.populate(profile, { path: "company.info" }, (err, p) => {
console.log(err);
console.log(p);
});
});
I get the following returned for the company field
company: {id: "5c318f56e3224b15e0fdbd07", position: "Stemuli"}
And the document that this id is linked to is the following:
{
"_id": {
"$oid": "5c318f56e3224b15e0fdbd07"
},
"employees": [
{
"$oid": "5c318f56e3224b15e0fdbd06"
}
],
"name": "Company",
"__v": 14
}
How can I get it to populate the actual company document instead of just the id?
Profile Schema
// Create Schema
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users"
},
company: {
id: { type: Schema.Types.ObjectId, ref: "industrypartners" },
position: { type: String }
},
work_experience: Array,
hometown: { type: String },
date: {
type: Date,
default: Date.now
}
});
module.exports = Profile = mongoose.model("profile", ProfileSchema);
Industry Partner Schema
// Create Schema
const IndustryPartnerSchema = new Schema({
name: {
type: String,
required: true
},
schools: [{ type: Schema.Types.ObjectId, ref: "schools" }]
});
module.exports = IndustryPartner = mongoose.model(
"industrypartner",
IndustryPartnerSchema
);
Try with this:
new Profile(profileFields).save().then(profile => {
Profile.populate(Profile, {
path: "company.info",
select: {
_id: 1,
employees: 1,
name: 1,
}
}, (err, p) => {
console.log(err);
console.log(p);
});
});
I'm new to MongoDB and Mongoose and I'm having some problems with it, to be more specific I've problems with populate, problem displayed below.
My Schema:
'use strict';
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
/* ------------------------------------- Field config ---------------------------------------- */
const UsersSchema = new Schema({
name: {
type: String,
required: true,
min: 3,
set: str => str.replace(/\b\w/g, l => l.toUpperCase())
},
lastname: {
type: String,
required: true,
min: 3,
set: str => str.replace(/\b\w/g, l => l.toUpperCase())
},
email: {
type: String,
required: true,
unique: true,
validade: {
validator: str => regExp.test(str)
}
},
password: {
type: String,
required: true,
min: 8
},
fcm:{
type: String,
required: true
},
birthDate: {
type: Date,
required: true,
get: convertToBR
},
gender: {
type: String,
enum: ['M', 'F'],
required: true
},
profileImage: {
type: String,
required: false,
get: alterUri
},
aboutMe: {
type: String,
max: 500
},
enabled: {
type: Boolean,
required: true,
default: true
},
createdAt: {
type: Date,
required: true,
default: new Date()
},
token: {
type: String,
required: true,
index: true
},
locations: {
type: [mongoose.Schema.Types.ObjectId],
require: false,
ref: 'Location'
},
lastVisitants: {
type: [{
user: mongoose.Schema.Types.ObjectId,
createAt: {
type: Date,
required: true,
default: new Date()
}
}],
required: false,
ref: 'Users'
}
}, {
toObject: {
virtuals: true,
getters: true,
setters: true
},
toJSON: {
virtuals: true,
getters: true,
setters: true
}
});
//Code bellow removed for make to easy know
Generated doc inside MongoDB:
{
"_id": "589288de533c9555163cf263",
"email": "luiz#sene.com",
"password": "CQziXoB6XrBFBTWe5s/kFsIGYqbtDPBBKQgADUZF9co=",
"name": "luiz Fernando",
"lastname": "Sene",
"birthDate": "1988-08-11T00:00:00.000Z",
"gender": "M",
"fcm": "34567890987654345678",
"token": "58979c08b048917ed8b434ac",
"createdAt": "2017-02-02T01:17:38.168Z",
"enabled": true,
"__v": 0,
"aboutMe": "algo sobre mim aqui mudar",
"locations": [
"5893e2e0c8a01b4ed21c8c39",
"5893e305c8a01b4ed21c8c3a",
"5893e32ac8a01b4ed21c8c3b",
"5893e34dc8a01b4ed21c8c3c",
"5893e92838bd205ba42c2c8a",
"5893ea888628c45d2bc6683a"
],
"profileImage": "images/589288de533c9555163cf263/1486330852976.png",
"lastVisitants": [
{
"createAt": "2017-02-05T19:23:17.697Z",
"_id": "58977ba99fc2b7485dbdbf26",
"user": "589778e22a9dd5449e4f92df"
}
]
}
My problem occurs when I try populate locations and lastVisitants.
My consult is below:
UsersSchema.findOne({_id: data.data.id}, {lastVisitants: true, locations: true})
.populate({
path: 'locations',
model: 'Location',
select: 'description',
options: {
limit: 1,
sort: {
createdAt: -1
}
}
})
.populate({
path: 'lastVisitants.user',
model: 'Users',
select: '_id lastVisitants',
options: {
limit: 5
//TODO: Add sort by createdAt
}
})
.exec((err, result) => {
if (err) {
Utils.callback(err, null, res);
return;
}
Utils.callback(null, result, res);
});
Result of my consult:
{
"_id": "589288de533c9555163cf263",
"lastVisitants": [
{
"_id": "58977c1c9fc2b7485dbdbf27",
"user": {
"_id": "589778e22a9dd5449e4f92df",
"lastVisitants": [
{
"_id": "58977c1c9fc2b7485dbdbf27",
"user": "589288de533c9555163cf263",
"createAt": "2017-02-05T19:23:17.697Z"
}
],
"profileImage": "http://192.168.0.19:3000/undefined",
"birthDate": {
"en": "NaN-NaN-NaN",
"br": "NaN/NaN/NaN"
},
"fullname": "undefined undefined",
"age": null,
"id": "589778e22a9dd5449e4f92df"
},
"createAt": "2017-02-05T19:23:17.697Z"
}
],
"profileImage": "http://192.168.0.19:3000/undefined",
"birthDate": {
"en": "NaN-NaN-NaN",
"br": "NaN/NaN/NaN"
},
"fullname": "undefined undefined",
"age": null,
"id": "589288de533c9555163cf263"
}
Result expected:
{
"_id": "589288de533c9555163cf263",
"locations":[
{
"_id": "5893ea888628c45d2bc6683a",
"description": "Cruzeiro - SP, Brasil"
}
]
"lastVisitants": [
{
_id: ""
user: {
"id": "58977ba99fc2b7485dbdbf26",
"fullname": "Fábio Pereira",
"profileImage": "http://192.168.0.19:3000/images/589288de533c9555163cf263/1486319528451.jpeg",
"gender": "M",
// more fields ...
},
createdAt: ""
}
]
}
My question is how can I make this query bring what I really desire?