find various entities by ids from multiple tables - node.js

I am using nestjs and typeorm for backend, currently have 3 entities in database. On many occasions, I need to find the records in different entites by ids passed from frontend. If any of them is not found, the function will return and stop proceeding.
It may receive 1 to 3 ids from frontend and the outcome should be clearly typed for next step.
I expect to use this function/method as follows:
const {user, organization, invitation}=await this.findEntities({userId, organizationId, invitationId})
// and when I try to do this, it should let me know that property "oganization" does not exist.
const { user, organization } = await this.findEntities({userId: 'abc'})
I stuck at the second use case. Although the return object does not contain any property named organization, it will not give the error prompt.
my code is as follows:
async findEntities(data: Ids) {
const { userId, organizationId, invitationId } = data;
const entities = await Promise.all([
userId ? this.userRepository.findOne({ where: { id: userId } }) : 1,
organizationId
? this.organizationRepository.findOne({
where: { id: organizationId },
})
: 1,
invitationId
? this.invitationRepository.findOne({
where: { id: invitationId },
})
: 1,
]);
if (entities.some((element) => element == null))
throw new NotFoundException();
return {
...(typeof entities[0] === 'number' ? null : { user: entities[0] }),
...(typeof entities[1] === 'number'
? null
: { organization: entities[1] }),
...(typeof entities[2] === 'number'
? null
: { invitation: entities[2] }),
};
}
Can you please help me improve it so that ts could prompt errors when imput and output do not match? Thanks.

Related

How to make sure that even if no data is given in the required field, it will consider is empty?

I am using Node.js and MongoDB. I want to make sure that if the user writes in the specific field, the database should be updated with that value, else it should be null.
Following is the code I am using:
exports.updatingUser = async (user_,request,res)=> {
let result = "";
const updateUserInfo = {
fullName: request.fullName,
userName: request.userName,
email :request.email,
password : request.password,
profileImage:request.profileImage,
backgroundImage:request.backgroundImage
};
await User.updateOne({_id:request._id},{$set:updateUserInfo})
.exec()
.then(docs => {
result = docs;
})
.catch(err => {
res.status(500).json({
error: err
});
});
return result;
}
This works when the user writes in the specific fields but not when any of the field is empty.
Try like this
fullName: request.fullName ? request.fullName : '', // You can put null if you want
Note: Need to put in all

Check if the body parameter is not null and update on MongoDB

I'm trying to update a document in MongoDB using NodeJS (NextJS). My current code is:
import connect from "../../util/mongodb";
async function api(req, res) {
if (req.method === "POST") {
const { id } = req.body;
const { name } = req.body;
const { email} = req.body;
const { anything1 } = req.body;
const { anything2 } = req.body;
if (!id) {
res.status(400).json({ "error": "missing id param" });
return;
}
const { db } = await connect();
const update = await db.collection("records_collection").findOneAndUpdate(
{ id },
{
$set: {
name,
email,
anything1,
anything2
}
},
{ returnOriginal: false }
);
res.status(200).json(update);
} else {
res.status(400).json({ "error": "wrong request method" });
}
}
export default api;
Everything is working. But I would like to request only the ID as mandatory, and for the other information, leave optional.
In this code, passing the id and name for example, the other three fields (email, anything1 and anything2) will be null in the document.
It is possible to implement the update without requiring all document information and ignore when body fields are null? (As a beginner in NodeJS and MongoDB, the only way to do that that comes to my head now is to surround it all by a lot of if...)
If I've understood your question correctly you can achieve your requirement using the body object in $set stage.
If there is a field which not exists in the object, mongo will not update that field.
As an example check this example where only name field is updated and the rest of fields are not set null.
Another example with 2 fields updated and 3 fields.
You can see how only is updated the field into object in the $set.
So you only need to pass the object received into the query. Something like this:
const update = await db.collection("records_collection").findOneAndUpdate(
{ id },
{
$set: req.body
},
{ returnOriginal: false }
);

Why it only returns the first id from my mock up database?

In short I am trying to create a simple api that would return the user with the matching id. I use postman to send requests to my localhost created using node.js with express. It works fine when I request the first user but throws in an error when requesting "John". I am coding along a udemy course and can't figure out what the issue is other than the material is outdated. The error is "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"
users: [
{
id: "123",
name: "Sally",
email: "sally#gmail.com",
password: "bananas",
entries: 0,
joined: new Date(),
},
{
id: "124",
name: "John",
email: "john#gmail.com",
password: "apples",
entries: 0,
joined: new Date(),
},
],
};
app.get("/profile/:id", (req, res) => {
const { id } = req.params;
let found = false;
database.users.forEach((user) => {
if (user.id === id) {
found = true;
return res.json(user);
}
if (!found) {
res.json("User not found");
}
});
});
From the MDN Web Docs:
There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
Early termination may be accomplished with:
A simple loop
A for...of
loop
[Array.prototype.every()][every]
[Array.prototype.some()][some]
[Array.prototype.find()][find]
[Array.prototype.findIndex()][findIndex]
This means that your loop will run through all elements and in fact call res.json multiple times resulting in the ERR_HTTP_HEADERS_SENT error . There are many ways to fix this, here's an one example:
app.get("/profile/:id", (req, res) => {
const {id} = req.params;
for (const user of database.users) {
if (user.id === id) {
return res.json(user);
}
}
res.json("User not found");
});

Create a new mongoose object with optional parameters from a request

I have a fairly long and complicated nested objected with optional objects inside (see below). I have a request coming in that could have some fields/objects missing - how can I handle that? Can I just use the "?" operand - I have tried but can't seem to get it working. Is there another method I could try?
const product = new Product({
prodID: req.body.prodID,
prodComponents: {
textComponent :{
item: req.body.prodComponents.textComponent.item ? req.body.prodComponents.textComponent.item : null
}
imageComponent:{
item: req.body.prodComponents.imageComponent.item ? req.body.prodComponents.imageComponent.item : null
}
}
)};
There are plenty of ways to resolve your problem. The variable: req.body is just another object as almost everything in javascript.
I'd recommend taking that object and parse it into variables or other object that your program or data model will handle with no exceptions of access into empty or undefined fields.
function createProductDtoToProduct(data) {
const model = {
prodID: data.prodID,
prodComponents: {
textComponent: {
item: null
},
imageComponent: {
item: null
}
}
};
if (data.prodComponents && data.prodComponents.textComponentItem)
model.prodComponents.textComponent.item = {
id: data.textComponentItem.id,
title: prodComponents.textComponentItem.title || "defaultTitle",
}
if (data.prodComponents && data.prodComponents.imageComponentItem)
model.prodComponents.imageComponent.item = {
id: data.imageComponentItem.id,
title: prodComponents.imageComponentItem.title || "defaultTitle",
}
return model;
}
router.post("/createProduct", async (req, res) => {
const product = new Product(createProductDtoToProduct(req.body));
await db.save(product);
return "OK";
});
Also you can validate the body of the request with many tools such as:
https://express-validator.github.io/docs/

Make api call if value from mongoDB is null

I am developing an app and I am using MEAN stack. I have values saved in a database using MongoDB. I want to use those values to make API calls but only if a value is null. Now it is successfully getting those values from the database and making the calls to the API but I don't know how to check if the value is null, I have tried basically everything but I think I don't understand completely NodeJS and that it is asynchronous. This is the code that works but doesn't check if the value is null:
var makeApiCalls = function (workerId) {
var Model = mongoose.model('Tweet'.concat(workerId), Tweet.tweetSchema);
return Model.find({},{ _id: 1, message: 1}).then(messages =>
Promise.all(
messages.map(({ _id, message }) =>
api.sentiment(message).then(result =>
Model.findOneAndUpdate({ _id }, { resultOfTheCall: result }, { new: true })
.then( updated => { console.log(updated); return updated })
)
)
)
)
};
The mongoose model has a field called resultOfTheCall and I need to check if that value is null and only in that case, I want to make a call to the API with the field message.
This is the console.log of one of the message:
{
_id: 5b85c83b413a2b1473e7122a,
date: 'Tue Aug 28 22:10:02 +0000 2018',
message: 'la gente quiere y no viene',
resultOfTheCall: 0.5931016939587707,
__v: 0 }
Simply filter the messages before making the Promise.all.
var makeApiCalls = function(workerId) {
var Model = mongoose.model('Tweet'.concat(workerId), Tweet.tweetSchema);
return Model.find({}, {
_id: 1,
message: 1,
resultOfTheCall: 1
}).then(messages => {
// filter the mssages here those for which to make the call and the others
var toCallArray = messages.filter(x => x.resultOfTheCall == null)
var noCallArray = messages.filter(x => x.resultOfTheCall != null)
// now do the calls for only those which do not have resultOfTheCall
return Promise.all(
toCallArray.map(({_id, message}) =>
api.sentiment(message).then(result =>
Model.findOneAndUpdate({
_id
}, {
resultOfTheCall: result
}, {
new: true
})
.then(updated => {
console.log(updated);
return [...noCallArray, ...toCallArray]
})
)
)
)
})
};

Resources