How to use both 'include' and 'attributes' in 'findByPk' statement in Sequelize? - node.js

How to use both 'include' and 'attributes' in 'findByPk' statement in Sequelize. This is my code:
exports.findOne = (req, res) => {
var id = req.params.id;
User.findByPk(id,
{
include: ["roles"]
},
{
attributes: {
exclude: ['password']
}
}
)
.then(data => {
res.send({"data": data, "resultCode": 1, "message": ""});
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving users."
});
});;
}
But it only works when I use 1 of 2 only.
If I just use: attributes: { exclude: ['password']} the result is as follows:
{
"data": {
"id": 1,
"username": "admin",
"email": "admin#gmail.com",
"createdAt": "2021-09-27T04:22:56.660Z",
"updatedAt": "2021-09-27T04:22:56.660Z"
},
"resultCode": 1,
"message": ""
}
If I just use: {include: ["roles"]} so the result is as follows
{
"data": {
"id": 1,
"username": "admin",
"email": "admin#gmail.com",
"password": "$2a$08$m54ioIwzpZRVC9/HqkHyqezOornjmvT9pDEJcOhHbNcSmLOfw3Sg.",
"createdAt": "2021-09-27T04:22:56.660Z",
"updatedAt": "2021-09-27T04:22:56.660Z",
"roles": [
{
"id": 2,
"name": "moderator",
"createdAt": "2021-09-27T04:20:46.956Z",
"updatedAt": "2021-09-27T04:20:46.956Z",
"user_roles": {
"createdAt": "2021-09-27T04:22:56.791Z",
"updatedAt": "2021-09-27T04:22:56.791Z",
"roleId": 2,
"userId": 1
}
},
{
"id": 3,
"name": "admin",
"createdAt": "2021-09-27T04:20:46.956Z",
"updatedAt": "2021-09-27T04:20:46.956Z",
"user_roles": {
"createdAt": "2021-09-27T04:22:56.791Z",
"updatedAt": "2021-09-27T04:22:56.791Z",
"roleId": 3,
"userId": 1
}
}
]
},
"resultCode": 1,
"message": ""
}
How to use both in my code? Because I dont want to show 'password' field in my result but I want to show the roles of user in my result. How to do like that. Thanks you in advanced

Options should be in 1 object like this.
User.findByPk(id,
{
include: ["roles"],
attributes: {
exclude: ['password']
}
})

Related

Why $or is not working properly in mongoose with regular expression

I'm trying to fetch documents which contain whatever I pass in url for filter which must present in title field or in tasks array of those documents:
example: localhost:4000/search?filter=Morning. here I'm looking for documents which contain Morning in their title or in their tasks.
But when I'm hitting the Api it is returning me all the documents.
{
"success": true,
"message": "Successfully fetched todos",
"filteredArray": [
{
"_id": "6386e34e2c65763cf25008f3",
"toDoTitle": {
"title": "Morning routines",
"_id": "6386e34e2c65763cf25008f4",
"createdAt": "2022-11-30T04:59:58.940Z",
"updatedAt": "2022-11-30T04:59:58.940Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e34e2c65763cf25008f5",
"createdAt": "2022-11-30T04:59:58.941Z",
"updatedAt": "2022-11-30T04:59:58.941Z"
},
"createdAt": "2022-11-30T04:59:58.941Z",
"updatedAt": "2022-11-30T04:59:58.941Z",
"__v": 0
},
{
"_id": "6386e3552c65763cf25008f7",
"toDoTitle": {
"title": "Morning",
"_id": "6386e3552c65763cf25008f8",
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e3552c65763cf25008f9",
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z"
},
"createdAt": "2022-11-30T05:00:05.813Z",
"updatedAt": "2022-11-30T05:00:05.813Z",
"__v": 0
},
{
"_id": "6386e35f2c65763cf25008fb",
"toDoTitle": {
"title": "evening",
"_id": "6386e35f2c65763cf25008fc",
"createdAt": "2022-11-30T05:00:15.809Z",
"updatedAt": "2022-11-30T05:00:15.809Z"
},
"toDoTasks": {
"tasks": [
"code",
"sleep",
"code",
"eat",
"code"
],
"_id": "6386e35f2c65763cf25008fd",
"createdAt": "2022-11-30T05:00:15.809Z",
"updatedAt": "2022-11-30T05:00:15.809Z"
},
"createdAt": "2022-11-30T05:00:15.810Z",
"updatedAt": "2022-11-30T05:00:15.810Z",
"__v": 0
},
{
"_id": "6386e3672c65763cf25008ff",
"toDoTitle": {
"title": "evening",
"_id": "6386e3672c65763cf2500900",
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z"
},
"toDoTasks": {
"tasks": [
"code"
],
"_id": "6386e3672c65763cf2500901",
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z"
},
"createdAt": "2022-11-30T05:00:23.977Z",
"updatedAt": "2022-11-30T05:00:23.977Z",
"__v": 0
},
{
"_id": "6386e3712c65763cf2500903",
"toDoTitle": {
"title": "night",
"_id": "6386e3712c65763cf2500904",
"createdAt": "2022-11-30T05:00:33.286Z",
"updatedAt": "2022-11-30T05:00:33.286Z"
},
"toDoTasks": {
"tasks": [
"code"
],
"_id": "6386e3712c65763cf2500905",
"createdAt": "2022-11-30T05:00:33.286Z",
"updatedAt": "2022-11-30T05:00:33.286Z"
},
"createdAt": "2022-11-30T05:00:33.287Z",
"updatedAt": "2022-11-30T05:00:33.287Z",
"__v": 0
}
]
}
This is my model
const mongoose = require("mongoose");
const schema = mongoose.Schema;
const title = new schema(
{
title:{
type: String,
trim: true
}
},
{
timestamps: true
}
);
const task = new schema(
{
tasks:[{ type: String,trim: true}]
},
{
timestamps: true
}
)
const toDoSchema = new schema({
toDoTitle : title,
toDoTasks: task
},
{
timestamps: true
});
const toDoModel = mongoose.model("toDo", toDoSchema);
module.exports = toDoModel;
this is my controller for filtering:
//importing model
const toDoModel = require('../models/ToDoModel');
//importing utils function
const toDosPerPage = require("../utlis/ToDosPerPage")
const searchController = async (req,res)=>{
try{
const {filter} = req.query
if(!filter) throw new Error("Please provide Something in filter to search");
const filteredArray = await toDoModel.find({
$or:[{title:new RegExp(filter,'i')},{tasks: new RegExp(filter,'i')}]
});
res.status(200).json({
success: true,
message: "Successfully fetched todos",
filteredArray
});
}
catch(err){
res.status(401).json({
success: false,
message: "Some error occuried",
error: err.message
})
console.log(err.message);
}
}
module.exports = searchController;
I want it to return only those documents which contain morning in their title or in their tasks fields.
to find in embeded document use dot .
const filteredArray = await toDoModel.find({
$or:[
{'toDoTitle.title':new RegExp(filter,'i')},
{'toDoTasks.tasks':new RegExp(filter,'i')}
]
});

Search Filter MongoDB Nestjs

When Implementing a search filter on a document withh populated documents and array of object, How can I enable the search filter to checkout the populated document or array for the searched word?
What I have only checks through the surface fields
async findAllFeedbacks(user: any, payload: FilterDto) {
if (payload.fields) {
const query = await this.distributionChannelsDocumentModel
.find({
[payload.fields]: {
$regex: `${payload.searchFilter}`,
$options: 'i'
},
})
.clone()
.where({ business: user.business })
.populate({
path: 'feedbackId',
// match: { 'feedbackId[payload.fields]': { $regex: `${payload.searchFilter}` } }
})
return { query, total: query.length }
} else {
const query = await this.distributionChannelsDocumentModel
.find()
.clone()
.where({ business: user.business })
.populate('feedbackId')
return { query, total: query.length }
}
}
Here is a response sample:
{
"query": [
{
"_id": "62a8645641b312b3a04a7233",
"feedbackId": {
"_id": "62a8642b41b312b3a04a722a",
"title": "Monthly Feedback test",
"questions": [
{
"title": "Rate Our Services test",
"subtitle": "Customer retention is our priority",
"type": "SMILEY"
}
],
"thankYouMessage": "Thanks for dropping a feedback",
"allowComment": true,
"allowEmail": true,
"allowFullName": false,
"allowAttachment": false,
"status": "Active",
"business": "62a83f5ab4b33de7307e9cb8",
"user": "62a83f59b4b33de7307e9cb6",
"createdAt": "2022-06-14T10:34:19.709Z",
"updatedAt": "2022-06-14T10:34:19.709Z",
"__v": 0
},
"user": "62a83f59b4b33de7307e9cb6",
"distributionChannelType": [
"email"
],
"meta": [
{
"sender": "string",
"subject": "string",
"positioning": "string",
"timing": "string",
"brandColor": "string"
}
],
"createdAt": "2022-06-14T10:35:02.092Z",
"updatedAt": "2022-06-14T10:35:02.092Z",
"__v": 0
},
{
"_id": "62b1c87510fae7f3a54b13b2",
"feedbackId": {
"_id": "62ac55d0b28630c3a8c9b940",
"title": "Yearly Feedback",
"questions": [
{
"title": "Rate Our Services",
"subtitle": "We love to hear from you! How is your Jumia food experience",
"type": "SMILEY"
}
],
"thankYouMessage": "Thanks for dropping a feedback",
"allowComment": true,
"allowEmail": true,
"allowFullName": false,
"allowAttachment": false,
"status": "Active",
"business": "62ac434542452ccb513f2241",
"user": "62ac434542452ccb513f223f",
"createdAt": "2022-06-17T10:22:08.863Z",
"updatedAt": "2022-06-17T10:22:08.863Z",
"__v": 0
},
"user": "62ac434542452ccb513f223f",
"distributionChannelType": [
"sms"
],
"meta": [
{
"position": "bottom",
"timing": "",
"brandColor": "#444"
}
],
"createdAt": "2022-06-21T13:32:37.895Z",
"updatedAt": "2022-06-21T13:32:37.895Z",
"__v": 0
}
],
"total": 2
}
In the above response, feedbackId is the populated document and questions is the array I would also want to search through when using the search filter

Making nested object 3 level in node js with sequelize from same table

right now i making a referral api like this in node js.
"id": 2,
"referralId": null,
"createdAt": "2022-05-13 15:15:16",
"updatedAt": "2022-05-13 15:15:16",
"child": [
{
"id": 1,
"referralId": 2,
"createdAt": "2022-05-13 12:41:00",
"updatedAt": "2022-05-13 12:41:00"
}
]
}
but i want it to have one more child. How is it possible.
{
"id": 2,
"referralId": null,
"createdAt": "2022-05-13 15:15:16",
"updatedAt": "2022-05-13 15:15:16",
"child": [
{
"id": 1,
"referralId": 2,
"createdAt": "2022-05-13 12:41:00",
"updatedAt": "2022-05-13 12:41:00",
"child": [
{
"id": 1,
"referralId": 2,
"createdAt": "2022-05-13 12:41:00",
"updatedAt": "2022-05-13 12:41:00"
}
]
}
]
}
also child is could be many.
right now this is the source. i am using sequelize btw. also child also come from same table as parent.
const getDownline = ((req, res) => {
model.referral.findOne({
where: {
id: req.body.id
}
}).then(data => {
model.referral.findAll({
where: {
referralId: req.body.id
}
}).then(child => {
data.setDataValue('child', child)
res.send(data)
}).catch(err => {
res.status(500).send(err)
})
})
})

How to get multiple association results in sequelize

i have problem fetching the association results.
I have two models
1 - User
2 - Project
User.hasMany(Project, { foreignKey : 'user_Id' });
Project.belongsTo(User, { foreignKey: { name: 'user_Id', type: DataTypes.UUID } })
when i fetch data through Project Model then corresponding user info is also fetched.
getAllProjects: async (req, res) => {
const projects = await Project.findAll({ include: User});
res.json({projects})
}
Result of above code
results
{
"projects": [
{
"id": "9bb3b99c-ac14-48fa-a0f2-e707f1d517ad",
"name": "this is project name",
"budget": "$34",
"details": null,
"days": null,
"deadline": null,
"user_Id": "02ef60af-0b1e-45e9-b393-55e124673143",
"start_date": null,
"status": 0,
"createdAt": "2022-03-23T03:02:56.000Z",
"updatedAt": "2022-03-23T03:02:56.000Z",
"User": {
"id": "02ef60af-0b1e-45e9-b393-55e124673143",
"name": null,
"email": null,
"password": null,
"userType": "client",
"createdAt": "2022-03-23T03:02:35.000Z",
"updatedAt": "2022-03-23T03:02:35.000Z"
}
}
]
}
But in reverse when i try to fetch user with their projects, user info is fetched but the associated projects are not fetched.
Code
getAllUsers: async (req, res) => {
const users = await User.findAll({inlcude: [{model: Project}]})
res.json({users})
}
** Result of above code**
{
"users": [
{
"id": "02ef60af-0b1e-45e9-b393-55e124673143",
"name": null,
"email": null,
"password": null,
"userType": "client",
"createdAt": "2022-03-23T03:02:35.000Z",
"updatedAt": "2022-03-23T03:02:35.000Z"
}
]
}
Please help me. Thanks in advance.
Simply correct typo from inlcude to include.
const users = await User.findAll({include: [{model: Project}]})

Unwind inside lookup in Mongoose

I have 2 entities to merge: Customer and Feedback. Feedback contains an embedded array of upvotes (Upvote)
A customer is not able to upvote more than once for a specific feedback.
What I would like to achieve is - given a specific feedback id - get the complete list of customers with an additional virtual attribute that states whether he/she upvoted the given feedback.
Customer.aggregate(
[
{
$match: { company_id: new ObjectID(req.user.company_id) }
},
{
$lookup: {
from: 'feedbacks',
let: { 'c_id': '$_id' },
pipeline: [
{
$unwind: '$upvotes'
},
{
$match: { $expr: { $eq: ['$upvotes.customer_id._id', '$$c_id'] } }
}
],
as: 'upvotes'
}
}
],
function(err, customers) {
if (err) {
console.log(err);
res.status(400).send(err);
} else {
res.send({ customers });
}
}
);
To do that I have to look through the list of upvotes for that specific feedback and, then, join it with the customer table using the customer_id.
The above mentioned approach does not work. Any suggestion what I am doing wrong?
Sample data (Feedback)
{
"size": 0,
"points": 50,
"status": "open",
"potential": 0,
"real": 5000,
"_id": "5c3d033271ceb7edc37d156c",
"title": "Custom Invoice Templates",
"description": "Provide an editor to create custom invoices.",
"owner_id": {
"_id": "5c3b684f7cec8be977c2a465",
"email": "maurizio#acme.com"
},
"company_id": "5c3b684f7cec8be977c2a462",
"project_id": "5c3b68507cec8be977c2a468",
"upvotes": [
{
"_id": "5c3fa5b371ceb7edc37d159a",
"comments": "bbbb",
"priority": "should",
"customer_id": {
"size": 0,
"potential": 0,
"real": 5000,
"_id": "5c3b68507cec8be977c2a485",
"name": "Oyomia Ltd."
},
"owner_id": {
"_id": "5c3b684f7cec8be977c2a465",
"email": "maurizio#acme.com"
}
}
],
"updatedAt": "2019-01-16T21:44:19.215Z",
"createdAt": "2019-01-14T21:46:26.286Z",
"__v": 0
}
Sample data (Customer)
{
"size": 0,
"potential": 0,
"real": 5000,
"_id": "5c3b68507cec8be977c2a485",
"name": "Oyomia Ltd.",
"contact": {
"_id": "5c40f8de71ceb7edc37d15ab",
"name": "Nick Page",
"email": "np#oyoma.com"
},
"company_id": "5c3b684f7cec8be977c2a462",
"deals": [
{
"value": 5000,
"_id": "5c3b68507cec8be977c2a487",
"name": "Armour batch",
"status": "won",
"type": "non_recurring",
"updatedAt": "2019-01-13T16:33:20.870Z"
}
],
"__v": 0,
"updatedAt": "2019-01-17T21:51:26.877Z"
}

Resources