Where am I getting it wrong? - express

I want to implement a functionality that enables users to filter/get businesses by location. This is my logic:
Declare a variable to hold the filtered array
Loop through the businesses
If the query is not undefined
Call the filter method on the businesses
if the query is equal to the location available in the database
Push the businesses with the specified location(s) into the array
return a success message and status code with the businesses in the
specified location or an error message with the appropriate status code.
This is the mock database:
const businesses = [
{
id: 1,
businessName: 'Kulikuli and Sons Limited',
description: 'We take you to heaven and back',
email: 'kososhi#gmail.com',
location: 'Kaduna',
category: 'Hospitality',
phoneNumber: '07033288342'
},
{
id: 2,
businessName: 'Rochas Limited',
description: 'We satisfy all your maintenance',
email: 'rochas2u#gmail',
location: 'Lagos',
category: 'Repairs and Maintenance',
phoneNumber: '07033288341'
},
{
id: 3,
businessName: 'Lekoto Travels',
description: 'Travel with us and you won\'t regret it',
email: 'lekotoboss#gmail.com',
location: 'Kaduna',
category: 'Travels and Tours',
phoneNumber: '07033288344'
},
];
This is the method to control the route: GET /businesses?location=<location>
static filterByLocation(req, res) {
const filteredLocation = [];
for (let i = 0; i < businesses.length; i += 1) {
if (typeof req.query.location !== 'undefined') {
businesses.filter((business) => {
if (business.location === req.query.location) {
filteredLocation.push(business);
}
});
}
return res.status(200).send({
status: 'Success',
location: filteredLocation
});
}
return res.status(404).send({
status: 'Fail',
message: 'Location not found'
});
}
However, the code isn't working as expected. Where am I getting it wrong?

try this, Filter function return filtered result not need to push in array based on condition, and res.send does not return JSON so you have to use res.json() or res.send(JSON.stringify(json)). You are returning response from inside for loop that will not work.
static filterByLocation(req, res) {
const filteredLocation = businesses.filter((business) => {
return business.location === req.query.location;
});
if (filteredLocation.length !== 0)
return res.status(200).json({
status: 'Success',
location: filteredLocation
});
return res.status(404).json({
status: 'Fail',
message: 'Location not found'
});
}

Related

Error: Exception in HostFunction: Attempting to create an object of type 'sets' with an existing primary key value '6' in react native

I'm trying to store history of workout in realm, my addHistory function looks like this
export function addHistory(workout, exercise, sets, _id) {
console.log({
workout,
exercise,
sets,
_id,
});
if (
_id !== undefined &&
workout !== undefined &&
exercise !== undefined &&
sets !== undefined
) {
// return console.log("HISTORY ", { workout, exercise, sets, _id });
return realm.write(() => {
return realm.create("workoutData", {
_id: _id,
exercise,
workout,
sets,
workoutDate: new Date(Date.now()),
});
});
} else {
alert("History is incomplete");
}
}
Schema of the workoutData is as follows:
exports.workoutData = {
name: "workoutData",
primaryKey: "_id",
properties: {
_id: "int",
workout: "workouts",
exercise: "exercise",
workoutDate: "date",
sets: "sets[]",
},
};
Now when I add sets and click on finishWorkoutHandler the logic works fine before the addHistory function but when addHistory is executed it throws the error as stated in the question.
//finish workout handler
const finishWorkoutHandler = () => {
if (sets.length == 0) {
return;
}
let setsFromRealm = realm.objects("sets");
let workoutData = realm.objects("workoutData");
let setsArray = [];
exercises.forEach((exercise) => {
sets
.filter((items) => items.exercise._id == exercise._id)
.forEach((sets) => {
let _id = 0;
if (setsFromRealm.length > 0) {
_id = realm.objects("sets").max("_id") + 1;
}
addSet(
sets.name,
parseInt(sets.weight),
parseInt(sets.reps),
parseInt(sets.rmValue),
sets.isHeighest,
sets.exercise,
_id,
sets.profile,
sets.failedSet,
sets.warmupSet,
sets.notes
);
let indiSet = {
name: sets.name,
weight: parseInt(sets.weight),
reps: parseInt(sets.reps),
rmValue: parseInt(sets.rmValue),
isHeighest: sets.isHeighest,
_id: _id,
profile: sets.profile,
failedSet: sets.failedSet,
warmupSet: sets.warmupSet,
notes: sets.notes,
createdDate: new Date(Date.now()),
};
setsArray.push(indiSet);
});
let workoutDataId = 0;
let setsArrcopy = setsArray;
console.log("SETS ", realm.objects("sets"));
console.log("SETS ", setsArrcopy);
if (workoutData.length > 0) {
workoutDataId = realm.objects("workoutData").max("_id") + 1;
}
**WORKING AS EXPECTED TILL HERE**
// problem lies here
addHistory(params.workout, exercise, setsArrcopy, workoutDataId);
});
dispatch(setsEx([]));
goBack();
};
the structure of setsArrCopy containing sets is as follows
[
({
_id: 6,
createdDate: 2022-09-29T16:27:06.128Z,
failedSet: false,
isHeighest: false,
name: "Thai",
notes: "",
profile: [Object],
reps: 12,
rmValue: 64,
warmupSet: false,
weight: 56,
},
{
_id: 7,
createdDate: 2022-09-29T16:27:06.151Z,
failedSet: false,
isHeighest: false,
name: "Thsi 3",
notes: "",
profile: [Object],
reps: 10,
rmValue: 75,
warmupSet: false,
weight: 66,
})
];
the logic is also working fine in terms of assigning new ids to the sets being added in a loop. But somehow its throwing error when passing setArrCopy to addHistory function. Although its an array of sets not a single object?

Add object to array in nested json object - Redux

I'm getting a hard time adding an object to an array inside a JSON object.
This is my state:
const DATA =
{
data: [
{
id: 1,
routeName: 'my 2 route',
origin: 'Tel Aviv',
destination: 'Netanya',
date: '25-01-2021',
km: '60',
stops: [
{
id: 0,
address: 'test',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
},
{
id: 1,
address: 'adddress',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
}
],
},
{
id: 2,
routeName: 'my second route',
origin: 'Holon',
destination: 'Hadera',
date: '12-02-2021',
km: '70',
stops: [
{
id: 0,
address: 'address0',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer0',
tel: '00000000',
},
{
id: 1,
address: 'address1',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer1',
tel: '00000000',
},
],
},
],
}
I don't know how to write the reducer, tried few ways but the state doesn't change.
My reducer gets the route id + stop to add this route.
I will be happy for some help here :)
You'll need to find the parent route using the route's id, and then you'll need to create a new stops array by spreading, and adding the new stop.
You can use Array.findIndex() to find the actual route, and the slice the array, and update the route. However, another simple option is to map the data's routes, and update the route with the matching id.
const routeReducer = (state, { type, payload: { routeId, stop } }) => {
switch (type) {
case 'ADD_STOP':
return {
...state,
data: state.data.map(route => route.id === routeId ? {
...route,
stops: [...route.stops, stop]
} : route)
}
}
}
Usually in redux it's better to normalize the state, which makes it easier to update single items.
You could have a reducer that did something like this:
const updateItemInArray = (array, itemId, updateItemCallback) => {
return array.map(item => {
if (item.id !== itemId) return item;
// Use the provided callback to create an updated item
return updateItemCallback(item);
});
};
const data = (state = [], action) => {
switch (action.type) {
case 'ADD_STOP_SUCCESS':
return updateItemInArray(state, action.payload.routeId, (item) => ({...item, stops: [...item.stops, action.payload.stop]}))
default: return state;
}
}
When the action.type 'ADD_STOP_SUCCESS' is called the payload of the action would contain the new stop object you are wanting to add to the state.

Trying to update a my Express Data base using postman

How do I update my database using Postman?
I'm trying to learn Express using Postman to test different types of requests, but I can't figure out how to update my data set. This is the structure of the data set I'm using.
var DB = [
{ category: 'Pets',
products: [
{ name: 'banjo',
color: 'grey',
mean: true,
description: "meows"
},
{ name: 'rigby',
color: 'black and white',
mean: false,
description: 'barks'
}]}]
Lets say I want to add another pet into the pets category so in products
{name: frank, color: orange, : mean: false: description: glubs}
I cant figure out how to add it correctly in Postman so that itll update. My code for the update is as follow:
app.post("/product/add", (req, res) => {
var category = req.body.category;
const { name, color, mean, description } = req.body;
var product = { name:name, color:color, mean:mean, description:description }; console.log(product);
var index = DB.findIndex(x => x.category == category);
if(index !== -1){
var indexProduct = DB[index].products.findIndex(x => x.name == product.name); if(indexProduct !== -1){
DB[index].products.push(product);
res.status(200).send(DB);
} else {
res.status(200).send(`Product already added to category.`);
};
} else {
res.status(200).send(`Category not found.`);
} });
Thanks in advance! Also sorry for the format.
There are a lot of repetitions, destructured variables that are not needed and syntactic errors in your code. Start by breaking down your problem into smaller chunks that are more manageable and then, test your endpoint with postman.
Let's start with your data and how it is structured:
var DB = [{
category: 'Pets',
products: [{
name: 'banjo',
color: 'grey',
mean: true,
description: "meows"
},
{
name: 'rigby',
color: 'black and white',
mean: false,
description: 'barks'
}
]
}]
// Lets say you want to add another pet into the pets category so in products
const obj = {
name: "frank",
color: "orange",
mean: false,
description: "glubs"
}
This is one of the things you could do to check if the object is not found and if not, you add it to your db.
DB.forEach((val) => {
if (val.products.name !== obj.name) {
DB[0].products.push(obj);
}
})
console.log(DB[0].products)
/**
*[{
name: 'banjo',
color: 'grey',
mean: true,
description: 'meows'
},
{
name: 'rigby',
color: 'black and white',
mean: false,
description: 'barks'
},
{
name: 'frank',
color: 'orange',
mean: false,
description: 'glubs'
}
]
*/
You postman request could look like this:
app.post("/product/add", (req, res) => {
// extract just what you need e.g name or ID if you have one...
const { name } = req.body;
// NOT efficient, best if you use a unique ID to look up
DB.forEach(value => {
if (value.products.name !== name) {
DB[0].products.push(req.body);
return res.status(200).send(JSON.stringify(DB));
}
else
return res.status(404).send("Not found or whatever");
});
});
OR using Array.prototype.findIndex you could do:
app.post("/product/add", (req, res) => {
const { name } = req.body;
const index = DB.forIndex(value => value === name);
if (index === -1) {
DB[0].products.push(req.body);
return res.status(200).send(JSON.stringify(DB));
}
else
return res.status(404).send("Not found or whatever");
}
});
Note: if your object name is the same than another one, your new object won't be pushed to the DB array. This would suggest you need to index your object with a unique identifier.

Sequelize query with a where clause on an include of an include

I'm struggling to create a query with sequelize.
Some context
I have the following models:
A Manifestation can have [0..n] Event
An Event belongs to one Manifestation (an Event cannot exist without a Manifestation)
A Place can have [0..n] Event
An Event belongs to one Place (an Event cannot exist without a Place)
A Manifestation can have [1..n] Place
A Place can have [0..n] Manifestation
I model the relations as the following:
Manifestation.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
Event.belongsTo(Manifestation)
Place.hasMany(Event, { onDelete: 'CASCADE', hooks: true })
Event.belongsTo(Place)
Manifestation.belongsToMany(Place, { through: 'manifestation_place' })
Place.belongsToMany(Manifestation, { through: 'manifestation_place' })
For me it seems rather correct, but don't hesitate if you have remarks.
The question
I'm trying to query the Place in order to get all Manifestation and Event happening in a given Place. But for the Event ones, I want to include them within their Manifestation even if the Manifestation doesn't happen in the given Place.
Below is the "JSON" structure I'm trying to achieve:
{
id: 1,
name: "Place Name",
address: "Place address",
latitude: 47.00000,
longitude: -1.540000,
manifestations: [
{
id: 10,
title: "Manifestation one",
placeId: 1,
events: []
},
{
id: 11,
title: "Manifestation two",
placeId: 3,
events: [
id: 5,
title: "3333",
manifestationId: 11,
placeId: 1
]
}
]
}
So I want to include the Manifestation with id: 11, because one of its Event occurs in the given Place (with id: 1)
Update (04/06/20): For now I rely on javascript to get the expected result
I figured out it would be nice if I posted my current solution before asking.
router.get('/test', async (req, res) => {
try {
const placesPromise = place.findAll()
const manifestationsPromise = manifestation.findAll({
include: [
{ model: event },
{
model: place,
attributes: ['id'],
},
],
})
const [places, untransformedManifestations] = await Promise.all([
placesPromise,
manifestationsPromise,
])
const manifestations = untransformedManifestations.map(m => {
const values = m.toJSON()
const places = values.places.map(p => p.id)
return { ...values, places }
})
const result = places
.map(p => {
const values = p.toJSON()
const relatedManifestations = manifestations
.filter(m => {
const eventsPlaceId = m.events.map(e => e.placeId)
return (
m.places.includes(values.id) ||
eventsPlaceId.includes(values.id)
)
})
.map(m => {
const filteredEvents = m.events.filter(
e => e.placeId === values.id
)
return { ...m, events: filteredEvents }
})
return { ...values, manifestations: relatedManifestations }
})
.filter(p => p.manifestations.length)
return res.status(200).json(result)
} catch (err) {
console.log(err)
return res.status(500).send()
}
})
But I'm pretty sure I could do that directly with sequelize. Any ideas or recommendations ?
Thanks
This is not optimum. But you can try it out:
const findPlace = (id) => {
return new Promise(resolve => {
db.Place.findOne({
where: {
id: id
}
}).then(place => {
db.Manefestation.findAll({
include: [{
model: db.Event,
where: {
placeId: id
}
}]
}).then(manifestations => {
const out = Object.assign({}, {
id: place.id,
name: place.name,
address: place.address,
latitude: place.latitude,
longitude: place.longitude,
manifestations: manifestations.reduce((res, manifestation) => {
if (manifestation.placeId === place.id || manifestation.Event.length > 0) {
res.push({
id: manifestation.id,
title: manifestation.id,
placeId: manifestation.placeId,
events: manifestation.Event
})
}
return res;
}, [])
})
})
resolve(out);
})
})
}
From this, you get all manifestations that assigned to place or have any event that assigns. All included events in the manefestations are assigned to the place.
Edit :
You will be able to use the following one too:
const findPlace = (id) => {
return new Promise(resolve => {
db.Place.findOne({
include: [{
model: db.Manefestation,
include: [{
model: db.Event,
where: {
placeId: id
}
}]
}],
where: {
id: id
}
}).then(place => {
db.Manefestation.findAll({
include: [{
model: db.Event,
where: {
placeId: id
}
}],
where: {
placeId: {
$not: id
}
}
}).then(manifestations => {
place.Manefestation = place.Manefestation.concat(manifestations.filter(m=>m.Event.length>0))
resolve(place);// or you can rename, reassign keys here
})
})
})
}
Here I take only direct manifestations in the first query. Then, manifestations that not included and concatenate.
I do not know if you figure it out by now. But the solution is provided below.
Search with Sequelize could get funny :). You have to include inside another include. If the query gets slow use separate:true.
Place.findAll({
include: [
{
model: Manifestation,
attributes: ['id'],
include: [{
model: Event ,
attributes: ['id']
}]
},
],
})
I tried to complete it in a single query but you will still need JavaScript to be able to get the type of output that you want.
(Note: 💡 You need manifestation which is not connected to places but should be included if a event is present of that place. The only SQL way to get that starts by doing a CROSS JOIN between all tables and then filtering out the results which will be a very hefty query)
I came up with this code(tried & executed) which doesn't need you to execute 2 findAll that fetches all data as what you are currently using. Instead it fetched only the data needed for final output in 1 query.
const places = await Place.findAll({
include: [{
model: Manifestation,
// attributes: ['id']
through: {
attributes: [], // this helps not get keys/data of join table
},
}, {
model: Event,
include: [{
model: Manifestation,
// attributes: ['id']
}],
}
],
});
console.log('original output places:', JSON.stringify(places, null, 2));
const result = places.map(p => {
// destructuring to separate out place, manifestation, event object keys
const {
manifestations,
events,
...placeData
} = p.toJSON();
// building modified manifestation with events array
const _manifestations = manifestations.map(m => {
return ({ ...m, events: [] })
});
// going through places->events to push them to respective manifestation events array
// + add manifestation which is not directly associated to place but event is of that manifestation
events.map(e => {
const {
manifestation: e_manifestation, // renaming variable
...eventData
} = e;
const mIndex = _manifestations.findIndex(m1 => m1.id === e.manifestationId)
if (mIndex === -1) { // if manifestation not found add it with the events array
_manifestations.push({ ...e_manifestation, events: [eventData] });
} else { // if found push it into events array
_manifestations[mIndex].events.push(eventData);
}
});
// returning a place object with manifestations array that contains events array
return ({ ...placeData, manifestations: _manifestations });
})
// filter `.filter(p => p.manifestations.length)` as used in your question
console.log('modified places', JSON.stringify(result, null, 2));

How to remove element from an array in mongoose

I have the following Schema:
// userSchema
{
_id: Schema.ObjectId,
email: { type: String, unique: true },
password: String,
boxes: [boxSchema]
}
// boxSchema
{
_id: Schema.ObjectId,
boxId: { type: String, unique: true },
boxName: String
}
I have data like this:
{
_id: random,
email: em#i.l,
password: hash,
boxes: [{ "boxId" : "box1", "boxName" : "Box 1"},
{ "boxId" : "box2","boxName" : "Box 2"},
{ "boxId" : "box3","boxName" : "Box 3"}]
}
I am trying to remove an element from boxes array with boxId: box1 and the code I tried was this:
User.findOne({
_id: req.body.id
})
.then(function (user) {
if (user) {
for (i in user.boxes)
if (user.boxes[i].boxId === 'box1')
user.boxes[i].remove();
res.json('removed');
}
})
.catch(function (err) {
....
});
But what happens is that it removes all the boxes which is residing, instead of the boxId: box1
What about using filter
User.findOne({
_id: req.body.id
})
.then(function (user) {
if (user) {
user.boxes = user.boxes.filter(function(box){
return box.boxId !== 'box1'
})
res.json('removed');
}
})
.catch(function (err) {
....
});
There are many ways to remove element from the array and are as follows:
1) Delete(): using this function will remove the element but will not change the array size and keep blank object after removal of element.
2)splice(): It works similar to delete() but remove blank places in array after removal of element.
3)filter(): It takes function as an argument and removes the element efficiently.