Express restful api expecting json array - node.js

I'm trying to integrate an Excel spreadsheet with my application using an node.js Express Restful Api. My API already accepts simple json like:
{
"num": "1",
"name": "Adams"
}
But now i need to send array of objects like:
[
{
"num": 1,
"name": "Adams"
},
{
"num": 2,
"name": "Phillips"
}
]
I'm using mongoose to connect to a mongoDB server and already the following function connected to a route in my api to accept single objects:
create_a_budget: function (req, res) {
var budget = new budgetModel({
user_id : req.body.user_id,
seq_budget : req.body.seq_budget,
date_done : req.body.date_done,
num_budget : req.body.num_budget,
medium : req.body.medium,
client_name : req.body.client_name,
email : req.body.email
});
budget.save(function (err, budget) {
if (err) {
return res.status(500).json({
message: 'Error when creating budget',
error: err
});
}
return res.status(201).json(budget);
});
}
But i don't have a clue about how to treat the array

You can simply pass an array of documents received from mongodb in res.json. res.json() will handle array properly. You dont have to do anything else. Example of the same:-
db.budget.find(query, (err, budgets) {
if(err) {
// handle error
}
return res.status(200).json(budgets);
});

Related

How to receive a list in Node.js from Flutter using a single API call to be stored in MongoDB

I am new to Node.js, and I need help with my project. I am using Flutter as my android application, a Node.js as my back-end, a Heroku as my API services, and a MongoDB as my database. The problem is, let's say I have 30 objects in a list of Flutter, how can I implement a code in Node.js to receive a whole list in a single API call?
So far I have implemented Node.js to receive the objects one by one, but, calling API back to back for 30 times is not very practical I would say. The list is a heart rate data for an exercise.
MongoDB. I want to store heart rate data in heartrateAerobicList:
{
"_id":{"$oid":"fdfg"},
"uniqueId":{"$numberInt":"1122"},
"name":"Jacob",
"objectives":[],
"completed_aerobic_exercise":[
{
"type":"Senaman Aerobik",
"exerciseId":"#52333",
"dateStart":"2022-08-03 18:09:51.073324",
"dateCompleted":"2022-08-03 18:12:02.831211",
"heartrateAerobicList":[
{
"value":{"$numberInt":"6"},
"date":"2022-08-03 18:09:51.073324"
},
{
"value":{"$numberInt":"11"},
"date":"2022-08-03 18:09:51.073324"
}
]
}
]
}
My back-end Node.js so far that receives the objects in the list one by one. This is the part I have a problem where I do not know how to receive a whole list in a single API call to be saved in the database:
//Update new heartrate data of an aerobic exercise
routes.post('/api/insert-aerobic-heartrate', async (req, res) => {
try {
await User.findOneAndUpdate(
{
uniqueId: parseInt(req.body.uniqueId),
"completed_aerobic_exercise.exerciseId": req.body.exerciseId,
},
{
$push: {
"completed_aerobic_exercise.$.heartrateAerobicList": {
value: parseInt(req.body.value),
date: req.body.date,
},
}
},
)
res.send("complete enter heartrate for aerobic");
}
catch(error) {
console.log("An error occurred " + error.message)
}
});
My API call in Flutter using HTTP packages:
var url2 = Uri.parse('https://dummy.herokuapp.com/api/insert-aerobic-heartrate'); //link is a dummy
var response2 = await http.post(url2,
body:
{
"uniqueId": "${widget.userId}",
"exerciseId": widget.exeID,
"value": "12",
"date": "2022-08-03 18:09:51.073324"
});
I hope I have provided all the necessary information for my problem.
Send the whole list in POST request
var url2 = Uri.parse('https://dummy.herokuapp.com/api/insert-aerobic-heartrate'); //link is a dummy
var response2 = await http.post(url2,
body:
{
"uniqueId": "${widget.userId}",
"exerciseId": widget.exeID,
"values": [
{"value": "12",
"date": "2022-08-03 18:09:51.073324"},
{
"value": "13",
"date": "2022-08-03 18:09:52"},
//....
]
});
On the backend change the place where you push a single object
$push: {
"completed_aerobic_exercise.$.heartrateAerobicList": {
value: parseInt(req.body.value),
date: req.body.date,
},
}
with the list which you received in the request
var values = req.body.values.map((x) => {
value: parseInt(x.value),
date: x.date
});
Sorry, I do not know how to add array into array in MongoDB, but I believe you should use $each operator for it, pls check https://codeforgeek.com/each-operator-in-mongodb/

Posting multiple documents using postman not working

I'm trying to post data using postman, but when I tried to use multiple documents, it shows blank in my mongodb. But when I try to insert a single document, it saves the data. Please correct me, I'm new to this
server.js
app.post('/bloodinventory', function(req, res) {
var bloodinventory= new Bloodinventories();
bloodinventory.blood_group = req.body.blood_group;
bloodinventory.blood_category = req.body.blood_category;
bloodinventory.num_stock = req.body.num_stock;
bloodinventory.save(function(err) {
if (err) {
res.json({ success: false, message: 'Blood Donation already exists!' });
} else {
res.json({ success: true, message: 'Blood Donation Created!' });
}
});
});
Then in my postman, I tried to insert this data:
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Then nothing shows in my mongodb, result:
_id:5c45c6a495788ec2c47f8c8b
__v:0
When you provide single document in your POST request
Example:-
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
}
it easly get request.body.blood_group, request.body.blood_category and show on
But when you pass Mutliple document in POST request in array form
{
"bloodinventories":[
{
"blood_group":"A_positive",
"blood_category":"whole blood",
"num_stock":11
},
{
"blood_group":"A_negative",
"blood_category":"platelet",
"num_stock":9
}
]
}
Now your request is getting a array so your request body contain bloodinventories. And you can access it as request.body.bloodinventories
Take this const and apply loop on it and insert all document.
Or Simply make API like this and always send array in every request of insert.
Bloodinventories.insertMany(request.body.bloodinventories).then((result) => {
//Success Message
}).catch(err => {
// Error Message
});
It May Help For You...

Timeout application-level join in mongoose with express

I have a timeout with my application-level join between two documents : Thread and Message.
I am trying to get all the Messages of my Thread with this code:
router.get('/:themeId/threads/:threadId/messages', function(req, res, next) {
Thread.findById(req.params.threadId, function(err, thread) {
if (err) return next(err);
Message.find({ _id: { $in: thread.messages } }), function(err, message) {
if (err) return next(err);
res.json(message);
}
});
});
Unfortunately, I got a timeout with my request which I tested Postman.
I had this message when I tested it:
Could not get any response
There was an error connecting to
http://localhost:3000/api/themes/5b1bb59d4210c50cf798da57/threads/5b1bb5e84210c50cf798da59/messages.
Also I checked that thread.messages is an array with another request:
GET http://localhost:3000/api/themes/5b1bb59d4210c50cf798da57/threads/5b1bb5e84210c50cf798da59 :
The result is below and from my Threaddocument :
{
"numberOfViews": 0,
"numberOfComments": 0,
"numberOfLikes": 0,
"numberOfThanks": 0,
"messages": [
"5b1bb5ad4210c50cf798da58",
"5b1bb6464210c50cf798da5a"
],
"_id": "5b1bb5e84210c50cf798da59",
"theme": "5b1bb59d4210c50cf798da57",
"title": "Title azerty",
"createdAt": "2018-06-09T11:11:36.358Z",
"updatedAt": "2018-06-09T11:13:41.062Z",
"__v": 1
}
From my understanding, my request should do a find Message in my array of Thread.messages...
But it seems I miss something.
Any idea to solve my timeout request?
Thanks a lot for your help.
Couple of suggestions to try out:
Make sure thread.messages is not an empty array. You can do this by asserting that its length is greater than 0.
In the clause Message.find({ _id: { $in: thread.messages } }), cast the string values to objectids by before sending it to the find clause. So you can do
var myobj1 = [];
thread.messages.forEach(element => {myobj1.push(Mongoose.Types.ObjectId(element)})
I found a solution with the populate of Mongoose and theses sources :
http://mongoosejs.com/docs/populate.html
https://alexanderzeitler.com/articles/mongoose-referencing-schema-in-properties-and-arrays/
Below the modified code:
router.get('/:themeId/threads/:threadId/messages', function(req, res, next) {
Thread.findById(req.params.threadId, function(err, thread) {
if (err) return next(err);
Message.find({_id: { $in : thread.messages } } )
.populate('messages')
.exec(function(error, messages) {
res.json(messages);
});
});
});

Deleting a single item from a database with mongodb

{
"_id": {
"$oid": "5a2de0a00d6baa43e8b925d0"
},
"name": "test",
"playList": [
{
"url": "https://p.scdn.co/mp3-preview/8aa799e60164f8a1fb311188d9d85ef65d7782c6?cid=ed36a056ee504173a3889b2e55cbd461",
"artist": "Kenny G",
"songName": "My Heart Will Go On (Love Theme from \"Titanic\")",
"_id": {
"$oid": "5a2de0ad0d6baa43e8b925d1"
}
},
{
"url": "https://p.scdn.co/mp3-preview/7c49854f18e6dfda6cd97ab5e8bc139d7ca82b7c?cid=ed36a056ee504173a3889b2e55cbd461",
"artist": "PRODUCE 101",
"songName": "PICK ME",
"_id": {
"$oid": "5a2de13b0d6baa43e8b925d2"
}
}
],
"__v": 0
}
I have a database called channels where each channels contain a playList as shown below. I want to delete a single item when a button is clicked. I can handle the onClick event part, but I am not sure how to implement the routes part.
I know that I start by doing something like
router.delete(''/channels/:id', function(req, res){
something here...
})
but how can I access a particular item (probably with a unique id?) and delete it from the DB?
EDIT
By using the GET below
router.get('/channels/:id',
isLoggedIn,
function(req, res) {
channel.findOne({'name':req.params.id},function(err,channeldata){
if(err || channeldata === null){
res.status(404).send({
message: 'Channel Not Found',
data: []
})
}
else {
res.status(200).json({
message: "channel to "+req.params.id+"success",
data:channeldata
})
}
})
});
I get the data for a single channel in my DB.
But since I am new to this stuff, I am not sure how to access each item of the playList and delete a single data.
EDIT2
var mongoose = require('mongoose');
var ChannelSchema = new mongoose.Schema({
name: {type:String,required:true},
playList: [{
songName: { type : String },
artist: { type : String },
url: { type : String }
}]
})
module.exports = mongoose.model('Channel',ChannelSchema);
You can try the following snippet that contains the DELETE (part of CRUD) endpoint for your resource collection (i.e. the channels):
router.delete('/channels/playlist/song', isLoggedIn, (req, res) => {
const channel_id = req.query.channelId;
const song_id = req.query.songId;
// the following query deletes a song form a playlist of a certain channel
channel.update({_id: ObjectId(channel_id)},{$pull:{playList:{_id:ObjectId(song_id)}}})
.exec()
.then(result => {
// for checking if document was found and deleted
// mongodb actually returns special object `result`
// which has its own certain fields
res.status(200).send({
status: "success",
message: result
});
})
.catch(error => {
// here we see if we had any problem with server or db itself
console.log(error)
res.status(500).send({
success: false,
message: "Something went wrong with DELETE /channels/:id"
})
})
});
I assume that you know what ObjectId() function does
if you do not have it declared, declare the following comment
in the beginning of the file (where you require everything)
const mongoose = require('mongoose'); // you must have this
const ObjectId = mongoose.Types.ObjectId; // gets the function
Let me know if this helps, or if you do not understand something - I will make an edit so that you get it.

How to add to array in MongoDB document with mongoose?

I've got a collection of spellbooks in a mongodb. One of my API calls in express through mongoose is a PUT where the user provides the ID of the document and then a body that contains an array of spells. I want to update the array of spells in the spellbook document with the array brought in from the client.
Here's what the document looks like:
{
"_id": {
"$oid": "56f999342c2bdee43869c33b"
},
"name": "malagar22",
"username": "zak",
"spells": [
"56bd4da932c3b8e88e3c113a",
"56bd4da932c3b8e88e3c113b"
],
"__v": 0
}
Here's what my API call looks like:
app.put('/api/spellbook/:id', function (req, res) {
Spellbook.findById(req.params.id, function(err,spellbook) {
if (err) {
res.json({info:'error during find spellbook',error:err});
};
if (spellbook) {
_.merge(spellbook, req.body);
spellbook.save(function(err) {
if (err) {
res.json({info:'error updating spellbook',error:err});
};
res.json({info:'spellbook updated successfully'});
});
} else {
res.json({info:'spell not found'});
}
})
});
As you can see, I'm finding the spellbook that matches the ID. Then I'm doing a lodash merge with the request body, which I imagine would match the spells array in the document with the spells array in the body, which I'll post below. Then we update.
Here's my request:
{
"spells":[
"56bd4daa32c3b8e88e3c1148"
]
}
I'm getting the success callback, but when I check the database, the document isn't being updated. Sorry if this is really simple. I'm an MS SQL guy and this is my first time using Express and Mongo.

Resources