Removing an object from an array by a property - javascript

I'm writing an endpoint to delete a record from a dummy database. The dummy database right now is written as an array of objects (it will then be changed to a class, then an actual database).
I have a dbHelpers.js file:
module.exports = {
createId(data) {
// ...
},
findById(data, recordId) {
// ...
},
deleteById(data, recordId) {
data.splice(data.findIndex(item => item.id === recordId), 1)
return data;
}
};
And i'm calling it in controllers/envelope.js
exports.deleteEnvelope = async (req, res) => {
try {
const { id } = req.params;
const envelopes = await dbEnvelopes;
const envelope = findById(envelopes, id);
if (!envelope) {
return res.status(404).send({
message: 'Envelope Not Found',
});
}
const updatedEnvelopes = deleteById(envelopes, id);
return res.status(200).send(updatedEnvelopes);
} catch (err) {
res.status(500).send(err)
}
};
However, for some reason, my findIndex function is not working and it's always returning -1. What is wrong with the function?
Below is the dummy db in config/db.js:
const envelopes = [
{
"id": 1,
"title": "Rent",
"budget": 1000
},
{
id: 2,
"title": "Groceries",
"budget": 300
},
{
id: 3,
"title": "Entertainment",
"budget": 400
}
]
module.exports = envelopes;

I think you can use array.filter to remove the object in array by matching the id.
deleteById(data, recordId) {
return data.filter(item => item.id !== recordId)
}

Related

use the filesystem module and the string.replace() to Substitute tokens in a nested object

When I run node index I get undefined. I am trying to use the filesystem module and the string.replace() method to replace tokens in a nested object in collections.js with values from another file (values.json). But when I run the code, nothing changes, and when I console.log finalData, I get undefined.
index.js
const fs = require("fs").promises;
async function dataReader(filePath, data) {
const result = await fs.readFile(filePath);
try {
return JSON.parse(result);
} catch (e) {
console.error(e);
}
}
//read values.json
(async () => {
const value = await dataReader("./values.json");
//read collection.json
const data = await dataReader("./collections.json");
//replace tokens in `collection.js` with `values.js`
let finalData = JSON.stringify(data);
Object.keys(value).forEach((token) => {
finalData = finalData.replaceAll(`__${token}__`, value[token])
});
// write/save the new replaced token values in collection.json
await fs.writeFile("./collections.json", finalData, (err) => {
if (err) {
console.error(err);
}
});
});
collection.js
{
"collection" : [
{
"fruit": "__fruit_type__",
"clothings":{
"item": "__clothing_type__}"
}
},
{
"fitness": "__fitness_equipment__",
"mindfulness": "app called __meditation_app__"
}
]
}
**values.js**
{
"clothing_type": "winter",
"fruit_type": "apple",
"fitness_equipment": "treadmill",
"meditation_app": "calm"
}
expected result:
The collection file after replacing the tokens will have below content:
{
"collection": [
{
"fruit":"apple",
"clothings":{
"item":"winter}"
}
},
{
"fitness":"treadmill",
"mindfulness":"app called calm"
}
]
}
Your collection.json is missing some comas and is not well formatted, try to change it to:
const data = {
"collection" : [
{
"fruit": "__fruit_type__",
"clothings": {
"item": "__clothing_type__"
}
},
{
"fitness": "__fitness_equipment__",
"mindfulness": "app called __meditation_app__"
}
]
}
const value = {
"clothing_type": "winter",
"fruit_type": "apple",
"fitness_equipment": "treadmill",
"meditation_app": "calm"
}
let finalData = JSON.stringify(data);
Object.keys(value).forEach((token) => {
finalData = finalData.replaceAll(`__${token}__`, value[token]);
});
console.log(JSON.parse(finalData))

data get from axios not sorted correctly

I need to get productId from query then get all data related to that product. This data should be sorted by createdAt month (id).
I tried .sort() but that didn't sort my data with proof that whenever i click on send button on postman, i receive untidy data.
API:
//...
router.get("/income", verifyTokenAndAdmin, async (req, res) => {
const productId = req.query.pid;
console.log(productId);
//...
product.jsx:
useEffect(() => {
const getStats = async () => {
try {
const res = await userRequest.get("orders/income?pid=" /*+productId */);
const list = res.data.sort((a, b) => {
return a._id - b._id;
});
list.map((item) =>
setPStats((prev) => [
...prev,
{ name: MONTHS[item._id - 1], Sales: item.total },
])
);
} catch (err) {
console.log(err);
}
};
getStats();
}, [productId, MONTHS]);
How to properly sort my data received from axios?
I tested Axios URL using postman and get method (localhost:5000/api/orders/income?pid=), it shows list of id (months) and total sales for each month:
[
{
"_id": 7,
"total": 170
},
{
"_id": 6,
"total": 224
},
{
"_id": 8,
"total": 200
}
]
Try this
const list = res.data.sort((a, b) => {
if(a._id>b._id){
return -1;
}
if(a._id<b._id){
return 1;
}
return 0;
});

map() in node.js, async vs sync?

I have a segment code like below running in Node.js. And I find it will always goes to else condiction, howerver with masterData is not null.
getOperationDetails(req, res) {
let sql = 'select a.*, b.s*';
sql += ` from ${paymentSheet} a left join ${paymentHisSheet} b on a.id= b.source_id `;
sql += ' where a.id=? ';
func.connPool(sql, id, (err, rows, field) => {
if (err) {
res.json({ code: 400, message: err })
} else {
let masterData = [];
let details = rows.map((row, idx) => {
if (idx === 0) {
masterData.push({
id: row.id,
name: row.name
});
}
return {
operator: row.operator_info,
comments: row.cmt,
status: row.sta
}
})
if (masterData.length > 0 ) {
masterData[0].details = details;
} else {
console.log(sql);
console.log(id);
console.log('=======================');
console.log(masterData);
}
res.json({ code: 200, message: 'ok', data: masterData })
}
})
For example, the console will show like below. Obviously masterData has value. It means 'if' condiction run before map(). Do I have to use async to wait the map() handle the data over?
allConnections:2
select a.*, b.* from payment a left join history b on a.id= b.source_id where a.id=?
83e588cd-9b4b-4592-ac7f-529bfaa9b231
=======================
allConnections:2
allConnections:2
[
{
id: '83e588cd-9b4b-4592-ac7f-529bfaa9b231',
name: 'Jeff'
}
]
My anaysis:
the rows from database should like below
83e588cd-9b4b-4592-ac7f-529bfaa9b231', 'Jeff', 'Operator Peter', 'OK', 0
83e588cd-9b4b-4592-ac7f-529bfaa9b231', 'Jeff', 'Operator Mary', 'NO', 1
83e588cd-9b4b-4592-ac7f-529bfaa9b231', 'Jeff', 'Operator Jet', 'OK', 2
or like below, means no details
83e588cd-9b4b-4592-ac7f-529bfaa9b231', 'Jeff', null, null, null
That is why I use masterData to separate. I think push() should not be taken out the map(), becasue rows maybe return nothing. Will it be like map() is over and push() is still running?
==== P.S. func.connPool====
let mysql = require('mysql');
let db = require('../configs/db');
let pool = mysql.createPool(db);
module.exports = {
connPool (sql, val, cb) {
pool.getConnection((err, conn) => {
if (err) {
console.log('Connection Error:' + err);
cb(err, null, null);
} else {
console.log('allConnections:' + pool._allConnections.length);
let q = conn.query(sql, val, (err, rows,fields) => {
pool.releaseConnection(conn);
if (err) {
console.log('Query:' + sql + ' error:' + err);
}
cb(err, rows, fields);
});
}
});
},
What I suspected is that the push operation is somehow delay because of some code that is not shown here (I am not certain yet).
I ran the following code so many times, I still could not reproduce your problem.
var rows = [
{
id: "123",
name: "test",
},
{
id: "123",
name: "test",
},
{
id: "123",
name: "test",
},
]
let masterData = [];
let details = rows.map((row, idx) => {
if (idx === 0) {
masterData.push({
id: row.id,
name: row.name
});
}
return {
id: row.id,
name: row.name,
}
})
if (masterData.length > 0 ) {
console.log("in");
} else {
console.log(masterData);
console.log('=======================');
}
Could you try whether it goes to else or not for this code.
From this piece of code you are pushing to MasterData only the first row.id and row.name.
( that is specified in the if conditional for just the first index idx === 0 )
So if thats the case you don't need to have this push thing inside the map.
You can take that out of the map and leave the iterator to create only the details array.
You can go with:
let details = rows.map(row => ({
operator: row.operator_info,
comments: row.cmt,
status: row.sta
})
);
let masterData = [{ id: rows[0].id, name: rows[0].name, details }]

Sequelize CreateOrUpdate Function

I am using node version v10.15.3 and "sequelize": "^4.22.8". When using bulkCreate I am getting double values in my db:
My model looks like the following:
module.exports = (sequelize, DataTypes) => {
const Company = sequelize.define('Company', {
name: DataTypes.STRING,
url: DataTypes.STRING,
symbol: DataTypes.STRING,
description: DataTypes.STRING,
}, {})
Company.associate = function(models) {
Company.hasMany(models.Rating)
};
return Company
};
I have created a custom createOrUpdateCompany() function. Find below my minimum executable example:
const models = require('./src/models');
const Company = require('./src/models').Company;
async function getAllCompanies() {
try {
let res = await Company.findAll()
return res;
} catch (error) {
console.log(error)
}
}
async function createOrUpdateCompany(dataArray) {
if (dataArray === undefined || dataArray.length === 0) return ''
let iss = []
const allCompanies = await getAllCompanies()
// flatten array
dataArray = [].concat.apply([], dataArray)
if (allCompanies !== undefined) {
// 1. remove exact dedupes from dataArray
dataArray = [...new Map(dataArray.map(obj => [JSON.stringify(obj), obj])).values()]
// 2. compare dataArray to allCompanies and remove difference
// dataArray = dataArray.filter(cv => !allCompanies.find(e => e.symbol === cv.symbol))
dataArray = dataArray.filter(cv => !allCompanies.find(e => e.symbol === cv.symbol))
// 3. Remove null values for link and "" values for name
dataArray = dataArray.filter(cv => !(cv.name === '' || cv.url === null))
}
try {
iss = await Company.bulkCreate(dataArray, {
fields: [
'name',
'url',
'symbol',
'description',
]
})
} catch (error) {
console.log(error)
}
return iss
}
let data = [{
"date": "9/14/2019",
"issuer": "Issuer6",
"name": "Name1",
"symbol": "Symbol2",
"url": "www.url.com"
}, {
"date": "9/11/2029",
"issuer": "Issuer3",
"name": "Name1",
"symbol": "Symbol1",
"url": "www.url.com"
}, {
"date": "8/13/2019",
"issuer": "Issuer1",
"name": "Name1",
"symbol": "Symbol1",
"url": "www.url.com"
}]
async function main() {
// setup db
await models.sequelize.sync({
force: true
})
await createOrUpdateCompany(data)
await createOrUpdateCompany(data)
await createOrUpdateCompany(data)
await createOrUpdateCompany(data)
console.log("##################### DONE #####################");
}
main()
When executing the above example I get the following in my db:
However, I would like to get only the following as result:
As you can see I only get two entries based on the unique result.
Any suggestions why my createOrUpdateCompany() is wrong?
I appreciate your replies!
There are 2 ways to achieve uniqueness in your result
Filter your array data before execution (Javascript stuff)
Unique elements from array
Make specific fields unique in the DB (composite unique) (Database stuff)Add Composite unique key in MySQL

'id' not defined when referencing JSON object in NodeJs endpoint

I am new to Javascript and have been following along with a course on NodeJs and am stuck on an exercise.
I am creating a basic CRUD API for 'genres' in a made up video store.
I have created all of the above but when I call any of the endpoint with a specific id I get an error.
TypeError: Cannot read property 'id' of undefined
at genres.find.g (/Users/richardcurteis/Desktop/NodeJsCourse/vidly-node/index.js:60:65)
at Array.find (native)
at findGenre (/Users/richardcurteis/Desktop/NodeJsCourse/vidly-node/index.js:60:26)
The issue is (I think) related to the findGenre method which checks to see if a genre with the matching id exists.
function findGenre(req) {
const genre = genres.find(g => g.id === parseInt(req.params.id));
if(genre) return genre;
false;
}
The json object is currently hardcoded.
This is the request (sent from Postman):
GET > http://localhost:5000/api/genres/1
This returns:
[
{
"id": 1,
"name": "Action"
},
{
"id": 2,
"name": "Horror"
},
{
"id": 3,
"name": "Drama"
}
]
I have checked against the solution and it appears to be the same implementation as mine, save for my refactoring repetitive checks and error codes.
Maybe I'm just going code blind, but maybe someone can see what I'm missing?
I have included the entire class (?) but like I said the error is related to the checking of the json objects id.
const Joi = require('joi');
const express = require('express');
const app = express();
app.use(express.json());
const genres = [
{ id: 1, name: 'Action' },
{ id: 2, name: 'Horror' },
{ id: 3, name: 'Drama' },
];
app.get('/api/genres', (req, res) => {
res.send(genres);
});
app.post('/api/genres', (req, res) => {
const { error } = validateGenreName(req.body);
if(error) return sendValidationError(res, error);
const genre = {
id: genres.length + 1,
name: req.body.name
};
genres.push(genre);
res.send(genre);
});
app.put('/api/genres/:id', (res, req) => {
const genre = findGenre(req);
if(!genre) return genreNotFoundError(res);
const { error } = validateGenreName(req.body);
if(error) return sendValidationError(res, error);
genre.name = req.body.name;
res.send(genre);
});
app.delete('/api/genres/:id', (res, req) => {
const genre = findGenre(req);
if(!genre) genreNotFoundError(res);
const index = genres.indexOf(genre);
genres.splice(index, 1);
res.send(genre);
});
app.get('/api/genres/:id', (res, req) => {
const genre = findGenre(req);
if(!genre) return genreNotFoundError(res);
res.send(genre);
});
// Functions
function findGenre(req) {
const genre = genres.find(g => g.id === parseInt(req.params.id));
if(genre) return genre;
false;
}
function genreNotFoundError(res) {
res.status(404).send('Genre not found');
}
function validateGenreName(genre) {
const schema = {
name: Joi.string().min(3).required()
};
return Joi.validate(genre, schema);
}
function sendValidationError(res, error) {
res.status(400).send(error.details[0].message);
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));
Now I see your problem. You have flipped (req, res) for the .get handler.
app.get('/api/genres/:id', (res, req) => {
const genre = findGenre(req);
if(!genre) return genreNotFoundError(res);
res.send(genre);
});
Should be
app.get('/api/genres/:id', (req, res) => {
const genre = findGenre(req);
if(!genre) return genreNotFoundError(res);
res.send(genre);
});
The same goes for .delete and .put.

Categories

Resources