Asynchronous request from database in node.js - javascript

i am making an asynchronous request to a database and then running a loop on the resultant data but i am getting only the last value while sending a response to front-end
routes.post('/data/qualitative/bivariate', async (req, res)=>{
const { colName1, colName2} = req.body;
var colNameObj1={};
var colNameArray1={};
colNameObj1[colName1]=1;
colNameObj1[colName2]=1;
colNameObj1['_id']=0;
//requesting data from database
const data= await dataModel.find({}, colNameObj1);
//filtering the data
const newData= data.map( (item)=>{
colNameArray1['x']= item[colName1];
colNameArray1['y']= item[colName2];
return colNameArray1
})
//in response i am getting just the data from the last index
res.json(newData)
})
In response i am getting just the data from the last index. Please advise how i can handle this asynchronous request

You must declare colNameArray1 inside the map function:
routes.post('/data/qualitative/bivariate', async (req, res)=>{
const { colName1, colName2} = req.body;
var colNameObj1={};
colNameObj1[colName1]=1;
colNameObj1[colName2]=1;
colNameObj1['_id']=0;
//requesting data from database
const data= await dataModel.find({}, colNameObj1);
//filtering the data
const newData= data.map( (item)=>{
var colNameArray1={};
colNameArray1['x']= item[colName1];
colNameArray1['y']= item[colName2];
return colNameArray1
})
//in response i am getting just the data from the last index
res.json(newData)
})

If you want all the rows, then you should push each object you can create in to an array. In the above code, you are overwriting over the same object.
Try updating the code to the following:
routes.post('/data/qualitative/bivariate', async (req, res)=>{
const { colName1, colName2} = req.body;
var colNameObj1={};
var colNameArray1={};
const dataList = [] // Create a empty array
colNameObj1[colName1]=1;
colNameObj1[colName2]=1;
colNameObj1['_id']=0;
//requesting data from database
const data= await dataModel.find({}, colNameObj1);
//filtering the data
data.forEach( (item)=>{
colNameArray1['x']= item[colName1];
colNameArray1['y']= item[colName2];
dataList.push(colNameArray1) // Push to the array
})
//in response i am getting just the data from the last index
res.json(dataList)
})

i found the issue and it has nothing to do with the asynchronous request and as mentioned above its confirmed that i am overwriting the object. Cloning the object using spread {... obj} has solved the issue. Thanks for help.

Related

Filter Array of objects (API response) based on flag in database

I am receiving a large array of objects using the below method:
const GetList = async () => {
const [data, error] = await GetList();
console.log(response);
This gives me back an array of 1000 elements, there is an isActive flag on every element and I need to filter out the elements that are not active.
I am not able to use
var resultFiltered = response.filter(obj =>{
return obj.isActive === 'true'
});
As it gives me an error message
The entire array is stored in the data variable, how can I filter out all elements that are not active?
I'm not sure why you are using response variable, since the value is fetched variable data, try filtering as shown below
const GetList = async () => {
const data = await GetList();
const resultFiltered = data.filter(obj => Boolean(obj.isActive) === true);
console.log(resultFiltered);
}
According to the error, the response variable is not an array-type variable please check that out. If it's an object then convert it into an array and then apply the filter function.
const resultFiltered = Object.values(response).filter(obj => obj.isActive === true);
Test the bellow code:
response.data.filter()

retrieving data from database according to query conditions

"_id":{"$id":"61b5eb36029b48135465e766"},
"name":"push-ups","link":"https://google.com",
"image":"https://google.com",
"gender":["0","1","2"],
"goal":["lw","gw","sf"],
"age":60,
"excersietype":"chest",
"__v":0
this is how my data is stored in database
and I want to fetch data according to 3 condition
I got 3 queries from front gender goal and age and according to that I have to retrieve data
const gender = req.query.gender;
const age = req.query.age;
const goal = req.query.goal
const level = req.query.level
if (level==='fb'){
const getdata = new Forbeg.find({gender:{$in:gender}},{age:{$lte:age}},{goal:{$in:goal}});
console.log(getdata)
}
Is this a good way to find the data because I am getting error
UnhandledPromiseRejectionWarning: MongooseError: `Model.find()` cannot run without a model as `this`. Make sure you are not calling `new Model.find()`
I am getting above error while fetching
The error is explicit : Make sure you are not calling 'new Model.find()'. Use const getdata = Forbeg.find(...).
However, you will immediately run into the next problem, as Mongoose models return thenables (Promise-like). console.log(getdata) will log Promise<pending>. You need to resolve your database call, either by doing
Forbeg.find(...).then( getdata => console.log(getData));
or (much more better!):
const getdata = await Forbeg.find(...);
console.log(getdata)
Even better, add .lean() to get simple JSON data instead of an array of Mongoose objects (faster), and .exec() to get a true Promise instead of a thenable :
const getdata = await Forbeg.find(...).lean().exec();
console.log(getdata)
Remove new operator
const getData = Forbeg.find({gender:{$in:gender}},{age:{$lte:age}},{goal:{$in:goal}});

array destructuring mongoose create

is there any other way to insert a data into mongoose without using array desctructuring
i have some code below, it doesnt work, also it doesnt insert correctly into database
const data = req.file.originalname.split('.')[0].split('_');
if (data.length < 5) throw new Error('Invalid file name');
const content = await fs.readFile(req.file.path, 'utf8');
await orders.create({ data, content });
i can make this work by using this code by using array desctructuring like below, what i want to know is there any way without using desctructuring, and just using variable data like my code above
const data = req.file.originalname.split('.')[0].split('_');
if (data.length < 5) throw new Error('Invalid file name');
// const [no_telp, type, timespan, name, unique_code] = data;
const content = await fs.readFile(req.file.path, 'utf8');
await orders.create({ no_telp, type, timespan, name, unique code, content });
What you are doing is not array destructuring. Array destructuring means pulling data out of array. An example array destructuring could be const listCopy = [...list] or const listAdded = [...list, 12, 48]. If you mean this part create({ no_telp, type, timespan, name, unique code, content }); you are providing neessary data into create method. You can create an abject beforehand and just send pass it to create method. const userData = { no_telp, type, timespan, name, unique code, content }; await orders.create(userData);
Additionally, what you are trying to save is a stringified data. After reading a file with fs.readFile() you must parse it to manipulate and save in database correctly. Try this:
const stringData = await fs.readFile(req.file.path, 'utf8');
const content = JSON.parse(stringData)
console.log(content) // see the data
const userData = {no_telp, type, timespan, name, unique code, content};
await orders.create(userData);

Appended data to formData in node.js...the data which i am posting to my api is always showing null?

Recently I was trying to append a lot of HTML form values to MongoDB database through an async process
this const createproperty are my MongoDB fields which i have taken in an array
const createProperty = ['propertyType',
'propertyName',
'bhkType',
'ownershipType',
'builtUpArea',
'propertyAge',
'floorType',
'floorNumber',
'numberOfFloors',
'city',
'expectedPrice',
]
.. these ids are some id's from the HTML form which i have put in an array
const myids = ['#thisPropertyType',
'#thisPropertyName',
'#thisBhk',
'#thisOwnerShip',
"#thisArea",
'#thisAge',
'#thisFloor',
'#thisFloorNo',
'#thisTotalFloor',
'#thisCity',
'#thisEp', ]
this newproperty will give me the values from the Html form, all of the values are stored in the form of an array and this for loop works just fine which gives me all the form values perfectly
const newProperty = new Array();
for(var i=0;i<myids.length;i++){
newProperty[i] = $(myids[i]).val();
}
const form = new FormData();
for(var i=0;i<newProperty.length;i++){
form.append(createProperty[i],newProperty[i]);
}
await createData(form);
this is the function which follows the async process
export const createData = async (data) => {
try{
for (var value of data.values()) {
console.log(value);
}
const res = await axios({
method: 'POST',
url: '/api/v1/myapi',
data
});
if(res.data.status==='success'){
alert('success');
}
console.log(data);
}
catch(err){
alert('error');
}
}
i console.logged the values from the createdata function, it gives me the values perfectly but it is not pushing the values to the mongodb server, when i look at the collection, there is an document which is created but it has no data in it..
please help me where have i done wrong, i'm not getting where did i go wrong..
Thank you so much for helping me out!!
axios expect the data to be JSON object not FormData
This will construct the body as JSON with keys from createProperty array
const data = {};
myids.forEach((id, index) => {
data[createProperty[index]] = $(myids[i]).val();
})
then you can send these values directly through axios
await createData(data)

How to parse Json data by chunks in NodeJs

I'm creating a REST API that gets raw data from the internet then apply a REGEX to it and return it in JSON format.
this is my function for getting Data as JSON.
first i'm using got() to get the raw data than I apply ANIME_LIST_REGEX.exec() to filter it with the regular expression to make it in JSON format.
async function getAnimeList(url) {
const {body} = await got(url);
let ANIME_LIST_DATA = ANIME_LIST_REGEX.exec(body)
if (!ANIME_LIST_DATA) {
return null;
}
return {
animeList: ANIME_LIST_DATA[1]
};
}
in this endpoint I'm retreiving the data from the 1st function and parsing the JSON, the return it as a response.
app.get('/anime-list', async (req, res, next) => {
const appData = await getAnimeList(URL_BASE_ANIME_LIST);
var listJson = JSON5.parse(appData.animeList)
res.json(listJson)
})
The issue is that the returned array is pretty big (5000 entries of js objects) and the request takes long time to return and show the array
What I want to do is to return a chunck of that array every time I call the function or reach the endpoint.
Tried several methods but none of them made sense.
Does anyone got an idea?
You can split the large array into a small chunk with Array.prototype.splice(). To determine the range of the chunk, you can pass queries to the endpoint.
app.get("/anime-list", async (req, res, next) => {
const appData = await getAnimeList(URL_BASE_ANIME_LIST)
var listJson = JSON5.parse(appData.animeList)
const from = req.query.from || 0
const count = req.query.count || 100
res.json(listJson.splice(from, count))
})
However, as others mention, calling getAnimeList() per request will cause another performance problem. I highly suggest you refactor the function to cache the result.

Categories