I am currently facing an issue with my Mongoose MongoDB setup and struggling to search for a userID within a nested array. Here's a breakdown of the situation:
I have two MongoDB models, "Patients" and "Teams". In the "Patients" model, I have a field called "team," which is a mongoose.Types.ObjectId referencing the "Teams" model. Within the "Teams" model, I have a field called "members," which is an array of objects containing the "id," "name," and "role" of team members.
Now, in my API endpoint, I am receiving a userID from the logged-in user, and I want to find all patients that have either the userID in their own "members" array or in the "members" array of the referenced team.
I have tried using various query methods like $elemMatch and $in, but so far, I haven't been successful in achieving the desired results. I have also experimented with aggregation, but unfortunately, it hasn't resolved the issue either.
Here's a simplified version of my API code:
const getAllPatients = async (req, res) => {
try {
const { page = 1, limit = 10, userID, tags = null, ...rest } = req.query;
const filter = {
...(tags && { tags: { $in: tags.split(",") } }),
...(!isEmptyObject(rest) && { $or: getSearchFilter(rest) }),
};
// The following block is where I'm facing the issue
const countPromise = await Patients.count({
$or: [
{
members: { $all: [userID] }, // This works for searching in patient's own members array
},
{
"team.members": { $all: [userID] }, // This is where I want to search in the referenced team's members array
},
],
});
const patientsPromise = await Patients.find({
$or: [
{
members: { $all: [userID] }, // Again, this works for searching in patient's own members array
},
// {
// "team.members": { $all: [userID] }, // This didn't work as expected
// },
],
...filter
});
const result = await Promise.all([countPromise, patientsPromise]);
const count = result[0];
const patients = result[1];
return res.status(200).json({
data: patients,
totalPages: Math.ceil(count / limit),
currentPage: parseInt(page),
});
} catch (e) {
console.log(e.message,"error");
return res.status(500).json({ error: e.message || `Something went wrong` });
}
};
Patient Model Schema :
const mongoose = require("mongoose");
const patientsSchema = new mongoose.Schema(
{
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
gender: {
type: String,
// required: true,
},
birthday: {
type: String,
},
email: {
type: String,
required: true,
validate: {
validator: function (v) {
return /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(v);
},
message: (props) => `Email ${props.value} is not valid`,
},
},
phone: {
type: String,
required: true,
},
address1: {
type: String,
},
address2: {
type: String,
},
state: {
type: String,
// required: true,
},
city: {
type: String,
// required: true,
},
zip: {
type: String,
// required: true,
},
tags: {
type: [mongoose.Types.ObjectId],
ref: "Tags",
},
members: {
type: [String],
// required: true,
},
team: {
type: mongoose.Types.ObjectId,
ref: "Teams",
// required: true,
},
chatBotEnabled: { type: Boolean, default: true },
smsConsent: { type: Boolean, default: false },
path: {},
},
{
timestamps: true,
}
);
module.exports = mongoose.model("Patients", patientsSchema);
Team Model Schema :
const mongoose = require("mongoose");
const teamsSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
unique: true
},
members: {
type: [{
"id": String,
"name": String,
"role": String
}],
required: true,
},
description:{
type:String,
required: true
}
},
{
timestamps: true,
}
);
module.exports = mongoose.model("Teams", teamsSchema);
I would really appreciate it if someone could guide me on how to properly search for the userID within the nested "members" array of the "Teams" model so that I can fetch the relevant patients accordingly.
Thank you in advance for your time and assistance!
try this changes in your code this will work
const getAllPatients = async (req, res) => {
try {
const { page = 1, limit = 10, userID, tags = null, ...rest } = req.query;
const filter = {
...(tags && { tags: { $in: tags.split(",") } }),
...(!isEmptyObject(rest) && { $or: getSearchFilter(rest) }),
};
// The following block is where I'm facing the issue
const countPromise = await Patients.count({
$or: [
{
members: { $all: [userID] },
},
{
$match: { "team": userID }, // or use below one
// $match: { "team": mongoose.Types.ObjectId(userID) },
},
],
});
const patientsPromise = await Patients.find({
$or: [
{
members: { $all: [userID] },
},
{
$match: { "team": userID }, // or use below one
// $match: { "team": mongoose.Types.ObjectId(userID) },
},
],
...filter
});
const result = await Promise.all([countPromise, patientsPromise]);
const count = result[0];
const patients = result[1];
return res.status(200).json({
data: patients,
totalPages: Math.ceil(count / limit),
currentPage: parseInt(page),
});
} catch (e) {
console.log(e.message,"error");
return res.status(500).json({ error: e.message || `Something went wrong`
});
}
};