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"
}
}
]);
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"
},
]
I have two schemas:
const userSchema = new Schema(
{
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
},
{
timestamps: true,
}
);
const userLikeSchema = new Schema(
{
userId: {
type: String,
required: true,
ref: 'User',
},
likedUserId: {
type: String,
required: true,
ref: 'User',
},
isActive: {
type: Boolean,
required: true,
default: true,
},
},
{
timestamps: true,
}
);
I am trying to get a list of users ordered descending by their number of likes.
I am not sure if the schema I did sql-like is correct.
I have written the following query:
const likedUsers = await UserLike.aggregate(
[
{
$group: {
_id: '$likedUserId',
likes: { $sum: 1 },
},
},
{ $sort: { likes: -1 } },
{
$lookup: {
from: 'users',
localField: 'likedUserId',
foreignField: '_id.str',
as: 'user',
},
},
]
);
I am trying to get a result like:
[
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": {
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
}
]
But instead I am getting the following which shows every user for each item:
[
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": [
{
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
{
"_id": "604bc703ea4bf93fb427056a",
"username": "krasniqi",
"password": "$2b$10$dnKumHhKNIfA6BM3uekymOpIdMFuQy9aYYKmGBxnW401CjTAuMLIy",
"createdAt": "2021-03-12T19:54:43.368Z",
"updatedAt": "2021-03-12T19:54:43.368Z",
"__v": 0
},
{
"_id": "604c90ab9f7b970cd46ff668",
"username": "matin",
"password": "$2b$10$CEUCaGk.JF5PBwsTBE3fRufVXzUBt.eLyo28eTt8zhBezVSFflMhS",
"createdAt": "2021-03-13T10:15:07.877Z",
"updatedAt": "2021-03-13T10:15:07.877Z",
"__v": 0
}
]
},
]
What am I missing ?
I think there is an issue about _id.str.
You have set your userLikeSchema wrong. You should have set the type of your ID fields mongoose.Schema.ObjectId:
const userLikeSchema = new Schema(
{
userId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'User',
},
likedUserId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'User',
},
isActive: {
type: Boolean,
required: true,
default: true,
},
},
{
timestamps: true,
}
);
After that, you can easily lookup by _id:
const likedUsers = await UserLike.aggregate(
[
{
$group: {
_id: '$likedUserId',
likes: { $sum: 1 },
},
},
{ $sort: { likes: -1 } },
{
$lookup: {
from: 'users',
localField: '_id',
foreignField: '_id',
as: 'user',
},
}, {
$unwind: "$user"
}
]
);
As a result of $lookup you will get an array of user, so you need to use $unwind to get a single User object.
Result will be like:
{
"_id": "604bb648be8680063009fddc",
"likes": 2,
"user": {
"_id": "604bb648be8680063009fddc",
"username": "muhamed",
"password": "$2b$10$EVYWZb4vl2TFGmIrCWe1sO/QogdU6/Ui8TgujY4PMKLJKIVOzmOi6",
"createdAt": "2021-03-12T18:43:20.806Z",
"updatedAt": "2021-03-12T18:46:17.635Z",
"__v": 0
},
}
I have this schema for users where followers/followed is array and the reference the same schema
var userSchema = new Schema({
username: { type: String, unique: true, trim: true, required: true },
password: { type: String, required: true },
followers: [{ type: Schema.Types.ObjectId, ref: "users" }],
followed: [{ type: Schema.Types.ObjectId, ref: "users" }],
registered: { type: Date, default: Date.now },
admin: { type: Number, default: 0 }
});
What I am looking for to return the follow status, if the _id is contains in followed array give me for example follow_status: 1
[
{
$match: { username: new RegExp(username, "i") }
},
{
$unwind: "$followers"
},
{
$lookup: {
from: "users",
localField: "followers",
foreignField: "_id",
as: "info"
}
},
{
$unwind: "$info"
},
{
$project: {
info: {
_id: 1,
username: 1,
avatar: { $ifNull: ["$avatar", ""] },
fullname: { $ifNull: ["$fullname", ""] }
}
}
},
{
$replaceRoot: { newRoot: "$info" }
},
{
$limit: 1000
}
]
Current pipeliens result
[
{
"_id": "5a906653f52e66c9c7a23cb6",
"username": "User1"
},
{
"_id": "5a908eb564a726cf8ec7e0a3",
"username": "User2"
}
]
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?