How to fetch data from multiple collections in MongoDB? - mongodb

How to fetch data from multiple collections in MongoDB by using a common field and sending data (in those fetched collections) using one response?
Employee Scheema:
const mongoose = require("mongoose");
const employeeSchema = new mongoose.Schema(
{
profilePic: {
type: String,
},
employeeID: {
type: String,
required: true,
},
employeeFirstName: {
type: String,
required: true,
},
employeeLastName: {
type: String,
required: true,
},
birthday: {
type: String,
},
streetNo: {
type: String,
},
city: {
type: String,
},
phoneNumber: {
type: String,
},
jobRole: {
type: String,
required: true,
},
NIC: {
type: String,
required: true,
unique: true,
},
companyEmail: {
type: String,
required: true,
unique: true,
},
status: {
type: String,
required: true,
},
resignDate: {
type: String,
},
jobType: {
type: String,
required: true,
},
candidateID: {
type: String,
required: true,
},
teamID: {
type: String,
},
lastSeen: {
type: String,
},
token: {
type: String,
},
},
{ timestamps: true }
);
module.exports = mongoose.model("employee", employeeSchema);
Acadamic Qualification Scheema:
const mongoose = require("mongoose");
const academicQualificaationSchema = new mongoose.Schema(
{
employeeID: {
type: String,
required: true,
},
ordinaryLevelResult: {
type: Array,
required: true,
},
advancedLevelResults: {
type: Array,
required: true,
},
achievements: {
type: Array,
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model(
"academicQualification",
academicQualificaationSchema
);
Professional Qualification Scheema:
const mongoose = require("mongoose");
const proffesionalQualificaationSchema = new mongoose.Schema(
{
employeeID: {
type: String,
required: true,
},
degree: {
type: Array,
required: true,
},
language: {
type: Array,
required: true,
},
course: {
type: Array,
required: true,
},
},
{ timestamps: true }
);
module.exports = mongoose.model(
"proffesionalQualification",
proffesionalQualificaationSchema
);
Controller:
exports.viewEmployees = async (req, res) => {
try {
let accQuali, profQuali;
const employees = await employeeSchema.find();
accQuali = await academicQualificaationSchema.find();
profQuali = await ProffesionalQualificationSchema.find();
if (employees || accQuali || profQuali) {
return res.status(200).json({ data: { employees, profQuali, accQuali } });
} else {
return res.status(404).json({ message: message });
}
} catch (err) {
return res.status(404).json({ err: err.message });
}
};
This controller is working properly and sends all data in 3 collections with the use of one response. But, I am comfortable if I will be able to Fetch data separately for each employee.

If you want to get the data from the three collections for specific employee or employees, you can use an aggregation pipeline with a $lookup stage, as suggested by #1sina1. For example:
db.employee.aggregate([
{
$match: {"employeeID": "IDA"}
},
{
$lookup: {
from: "academicQualification",
localField: "employeeID",
foreignField: "employeeID",
as: "academicQualification"
}
},
{
$lookup: {
from: "proffesionalQualification",
localField: "employeeID",
foreignField: "employeeID",
as: "proffesionalQualification"
}
}
])
As you can see on the playground

Related

Mongo db error getting Error validating $lookup value. err=$lookup against an expression value is not allowed in this atlas tier

I am creating express server for the project and I used the mongodb for the database. I am getting error,
Error validating $lookup value. err=$lookup against an expression value is not allowed in this atlas tier.
movies schema,
const mongoose = require("mongoose");
const MovieSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
desc: { type: String },
img: { type: String },
imgTitle: { type: String },
imgSm: { type: String },
trailer: { type: String },
video: { type: String },
year: { type: String },
limit: { type: Number },
genre: { type: String },
isSeries: { type: Boolean, default: false },
},
{ timestamps: true }
);
module.exports = mongoose.model("movies", MovieSchema);
My lists schema,
const ListSchema = new mongoose.Schema(
{
title: { type: String, required: true, unique: true },
type: { type: String },
genre: { type: String },
content: [
{ type: mongoose.Schema.Types.ObjectId, required: false, ref: "movies" },
],
},
{ timestamps: true }
);
lists schema has a content property and it's contains the ids of the movies.so I need to have get all movies in the list with sample size 4,so I write aggregation for the list schema for populating movies object in content property in list schema. So where is the bug in my code ?I hope your help!
so I coded it as,
const list = await List.aggregate([
{ $sample: { size: 4 } },
{
$lookup: {
from: "$movies",
foreignField: "_id",
localField: "content",
as: "content",
},
},
]);
}
res.status(200).json(list);

How to I resolve below graphql query in mongodb nested array

my model schema look like this
const mongoose = require("mongoose")
const userSchema = new mongoose.Schema(
{
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
select: false,
},
email: {
type: String,
required: true,
unique: true,
match: [
/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/,
"Please enter a valid email",
],
},
followers:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"user"
}
],
following:[
{
type:mongoose.Schema.Types.ObjectId,
ref:"user"
}
],
displayName: {
type: String,
required: false,
},
},
{ timestamps: true }
)
module.exports = mongoose.model("user", userSchema)
in this schema all working good like mutation work fine but when i fetch query of all user then in that query followers and following field return null like bellow image
and my graphql query is
const users = {
type: new GraphQLList(UserType),
description: "Retrieves list of users",
resolve(parent, args) {
return User.find()
},
}
and typedef is
const UserType = new GraphQLObjectType({
name: "User",
description: "User types",
fields: () => ({
id: { type: GraphQLID },
username: { type: GraphQLString },
email: { type: GraphQLString },
post:{
type: GraphQLList(PostType),
resolve(parent, args) {
return Post.find({ authorId: parent.id })
},
},
savePost:{
type:GraphQLList(savedPosts1),
resolve(parent, args) {
return SavePost.findById({ authorId: parent.id })
},
},
followers:{
type:GraphQLList(UserType),
},
following:{
type:GraphQLList(UserType)
}
// displayName: { type: GraphQLString },
}),
})
so please tell me how to i resolve that followers and following query in graphql with mongodb and tell me what i write in my userType typedef

MongoDB: Find items with the user id

I have a product collection and a user collection where I reference user to my product collection.
So far what I am trying to achieve here is to get only the products that are created by that user.
const getOwnerProduct = expressAsyncHandler(async (req, res) => {
const activeUser = await User.findById(req.user._id)
const pageSize = 10
const page = Number(req.query.pageNumber) || 1
const items = { user: { _id: activeUser } }
const count = await Product.countDocuments({ ...items } )
const products = await Product.find({ ...items }).limit(pageSize).skip(pageSize * (page - 1))
res.json({ products, page, pages: Math.ceil(count / pageSize) })
})
Here's the Product Schema:
const productSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true
},
email: {
type: String
},
rating: {
type: Number,
required: true,
default: 0
},
image: {
type: String,
required: true,
default: 0
},
}, { timestamps: true
})
And here's the userSchema:
const userSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
phone: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['administrator', 'productOwner', 'regular'],
default: 'regular'
}
}, { timestamps: true
})
Here's the router:
app.use('/api/products', productRoutes)
router.route('/').get(getProducts, admin).get(getOwnerProducts, productOwner)
For some reason this doesn't work. I think my query on mongodb is not correct.
Any idea what am I missing here?
Here instead of const products = await Product.find({ ...items }) you can try
await User.findById(req.user._id).forEach(element =>{Product.find({user=element._id})});
or
await User.findById(req.user._id).forEach(element =>{Product.find(user=element._id)});

find one with multiple conditions mongoose mongodb

I am trying to obtain data from mongodb. This is the scenario. Each user has a following property(array) that takes an array of users id.
The user model is as below
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
followers: [{ type: mongoose.Types.ObjectId, ref: "user" }],
following: [{ type: mongoose.Types.ObjectId, ref: "user" }],
});
in simple terms. I need to use two conditions where postedBy: { $in: req.user.following }, or postedBy:req.user._id
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
body: {
type: String,
required: true,
},
photo: {
type: String,
required: true,
},
likes: [{ type: mongoose.Schema.ObjectId, ref: "user" }],
comments: [
{
text: String,
postedBy: { type: mongoose.Schema.Types.ObjectId, ref: "user" },
},
],
postedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
},
});
I have not figured out the second condition to add in the code below.
router.get("/getSubPost", requireLogin, async (req, res) => {
try {
const result = await Post.find({
postedBy: { $in: req.user.following },
})
.populate("postedBy", "-password")
.populate("comments.postedBy", "_id name");
res.json({ result });
} catch (error) {
console.log(error);
}
});

MongoDB (mongoose) about refs

who can explain with example how to get from another schema user data (for example useravatar)
while i read about refs and i cant understand.
This is my code, but i want to send back not only article but with profile datas about author. How can i do this ? I have authorID already for this.
router.post('/get-article', (req, res) => {
const { id, authorID } = req.body.data;
Article.findByIdAndUpdate({ _id: id }, { $inc: { "pageview": 1 } }, (err, article) => {
if (err) return res.status(400).json({ NotFound: "Article Not Found" })
res.json({ article })
})
})
article schema
const schema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
title: { type: String, required: true },
image: { type: String, required: true },
content: { type: String, required: true },
email: { type: String, required: true },
author: { type: String, required: true, index: true },
added: { type: Date, default: Date.now },
pageview: { type: Number, default: 0 }
});
User schema
const schema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
username: { type: String, required: true },
email: { type: String, required: true },
facebookId: { type: String },
githubId: { type: String },
googleId: { type: String },
useravatar: { type: String, required: true },
userip: { type: String, required: true },
accessToken: { type: String },
date: { type: Date, default: Date.now }
});