API call giving empty array in nodejs - javascript

This is 'product.js' file, and when ever I am calling the api '/achaar/products/1', the value of val is giving empty in console. Other api calls like '/achaar/products' is working fine, but on calling with id this is not working.
const express = require('express')
const router = express.Router();
const json_data = require('./test_data');
const cons = require('./constants')
/*
url is : /achaar/products
replace test data with database datas
*/
router.get(cons.URLS.all_product,(req,res) => {
res.json(json_data)
})
router.get(cons.URLS.all_product+'/:id',(req,res) => {
console.log(req.params.id)
var val = json_data.achaar.filter(function (x) { return x.id === req.params.id })
console.log(val)
})
module.exports = router
Here is my test_data.js file
{
"achaar" : [
{
"id" : 0,
"name" : "Ginger Tangi",
"cost" : 2000
},
{
"id" : 1,
"name" : "Mango Khatta",
"cost" : 1200
},
{
"id" : 2,
"name" : "Gaas Dhari",
"cost" : 3000
},
{
"id" : 3,
"name" : "Cream Tangy",
"cost" : 1000
}
]
}

Because you use === and it was check value and type is equal
You should convert req.params.id to number because id of data is number.

Related

How to write a proper promise for a Firebase function that queries an external API with Axios, and saves JSON response in multiple Firestore Documents

I would be glad if I can get some help with my first question. I am an Android developer and I am currently doing a project which requires Firebase cloud functions, which I am new to.
I am calling an external API with Axios, and saving the JSON response into multiple Firestore documents. 4 out of 5 times that I call the function, it executes without error, but it does not write to Firestore, and the 1 time it writes to Firestore, it takes as long as 8 to 12 seconds to write the data.
I read something about promises and I applied to the function(to the best of my knowledge) but the problem persists. Please let an expert tell me what I am doing wrong. Below is my cloud function:
const functions = require("firebase-functions");
const axios = require("axios");
const admin = require("firebase-admin");
const api_token = "---------";
const includes = "------------";
const url = "------------" + api_token + includes;
exports.liveScores = functions.https.onRequest((req, res) => {
return axios.get(url)
.then(response => {
var data = response.data.data;
data.forEach(function(obj){
admin.firestore().collection("fixtures").doc(obj.id.toString()).set({
id : obj.id,
league_id : obj.league_id,
venue : obj.venue_id,
localteam_id : obj.localteam_id,
visitorteam_id : obj.visitorteam_id,
round_id : obj.round_id,
round_name : obj.round ? obj.round.data.name : null,
stage_id : obj.stage_id,
localteam_score : obj.scores.localteam_score,
visitorteam_score : obj.scores.visitorteam_score,
status : obj.time.status,
timestamp : new admin.firestore.Timestamp(obj.time.starting_at.timestamp, 0),
real_date : obj.time.starting_at.date,
minute : obj.time.minute,
injury_time : obj.time.injury_time,
localteam_formation : obj.formations.localteam_formation,
visitorteam_formation : obj.formations.visitorteam_formation,
visitorTeam : obj.visitorTeam.data.name,
localTeam : obj.localTeam.data.name,
local_team_logo : obj.localTeam.data.logo_path,
visitor_team_logo : obj.visitorTeam.data.logo_path,
season_id : obj.season_id,
referee : obj.referee ? obj.referee.data.fullname : null,
aggregate : obj.aggregate ? obj.aggregate.data.result : null,
venue_name : obj.venue && obj.venue.data.name ? obj.venue.data.name : null,
weather_type : obj.weather_report && obj.weather_report.type ? obj.weather_report.type : null,
weather_icon : obj.weather_report && obj.weather_report.icon ? obj.weather_report.icon : null,
temperature : obj.weather_report && obj.weather_report.temperature_celcius ? obj.weather_report.temperature_celcius.temp : null
}).then(() => {
console.log("Fixtures table complete...");
})
var no_of_events = obj.events.data.length;
for(var i=0; i < no_of_events; i++ ){
admin.firestore().collection("events").doc(obj.events.data[i].fixture_id.toString()).collection("all_events").doc(obj.events.data[i].id.toString()).set({
type : obj.events.data[i].type,
team_id : obj.events.data[i].team_id,
fixture_id : obj.events.data[i].fixture_id,
var_result : obj.events.data[i].var_result,
player_id : obj.events.data[i].player_id,
player_name : obj.events.data[i].player_name,
related_player_id : obj.events.data[i].related_player_id,
related_player_name : obj.events.data[i].related_player_name,
minute : obj.events.data[i].minute,
reason : obj.events.data[i].reason,
id : obj.events.data[i].id
}).then(() => {
console.log("Events table complete...");
})
}
for(var y=0; y < obj.lineup.data.length; y++){
admin.firestore().collection("lineup").doc(obj.lineup.data[y].fixture_id.toString()).collection("lineup").doc(obj.lineup.data[y].player_id.toString()).set({
fixture_id : obj.lineup.data[y].fixture_id,
team_id : obj.lineup.data[y].team_id,
player_id : obj.lineup.data[y].player_id,
player_name : obj.lineup.data[y].player_name,
number : obj.lineup.data[y].number,
position : obj.lineup.data[y].position,
formation_position : obj.lineup.data[y].formation_position,
captain : obj.lineup.data[y].captain
}).then(() => {
console.log("Lineup table complete...");
})
}
for(var x=0; x < obj.bench.data.length; x++){
admin.firestore().collection("bench").doc(obj.bench.data[x].fixture_id.toString()).collection("bench").doc(obj.bench.data[x].player_id.toString()).set({
fixture_id : obj.bench.data[x].fixture_id,
team_id : obj.bench.data[x].team_id,
player_id : obj.bench.data[x].player_id,
player_name : obj.bench.data[x].player_name,
number : obj.bench.data[x].number,
position : obj.bench.data[x].position,
formation_position : obj.bench.data[x].formation_position,
captain : obj.bench.data[x].captain
}).then(() => {
console.log("Bench table complete...");
})
}
for(var c=0; c < obj.stats.data.length; c++){
admin.firestore().collection("stats").doc(obj.stats.data[c].fixture_id.toString()).collection("all_stats").doc(obj.stats.data[c].team_id.toString()).set({
fixture_id : obj.stats.data[c].fixture_id,
team_id : obj.stats.data[c].team_id,
total_shots : obj.stats.data[c].shots && obj.stats.data[c].shots.total ? obj.stats.data[c].shots.total : null,
ongoal : obj.stats.data[c].shots && obj.stats.data[c].shots.ongoal ? obj.stats.data[c].shots.ongoal : null,
total_passes : obj.stats.data[c].passes && obj.stats.data[c].passes.total ? obj.stats.data[c].passes.total : null,
attacks : obj.stats.data[c].attacks && obj.stats.data[c].attacks.attacks ? obj.stats.data[c].attacks.attacks : null,
fouls : obj.stats.data[c].fouls,
corners : obj.stats.data[c].corners,
offsides : obj.stats.data[c].offsides,
possessiontime : obj.stats.data[c].possessiontime,
yellowcards : obj.stats.data[c].yellowcards,
redcards : obj.stats.data[c].redcards,
injuries : obj.stats.data[c].injuries,
saves : obj.stats.data[c].saves,
tackles : obj.stats.data[c].tackles
}).then(() => {
console.log("Stats table complete...");
})
}
})
return res.status(200).json(
console.log("successful")
)
})
.catch(err => {
console.log(err);
return res.status(500).json({
error: err
})
})
});
I would appreciate any kind of help.
Thank you.
You should probably not launch all those firestore queries simultaneously, but wait for each one to complete before launching the next one.
This is easier when you make the onRequest callback function async:
exports.liveScores = functions.https.onRequest(async (req, res) => {
try {
let response = await axios.get(url);
var data = response.data.data;
for (let obj of data) {
await admin.firestore().collection("fixtures").doc(obj.id.toString()).set({
id: obj.id,
/* ... */
});
console.log("Fixtures table complete...");
for (let eventData of obj.events.data){
await admin.firestore().collection("events").doc(eventData.fixture_id.toString()).collection("all_events").doc(eventData.id.toString()).set({
type: eventData.type,
/* ... */
});
}
console.log("Events table complete...");
for (let lineupData of obj.lineup.data) {
await admin.firestore().collection("lineup").doc(lineupData.fixture_id.toString()).collection("lineup").doc(lineupData.player_id.toString()).set({
fixture_id: lineupData.fixture_id,
/* ... */
});
}
console.log("Lineup table complete...");
/* ... etc ... */
}
console.log("successful");
return res.status(200).json({ message: "successful" });
} catch(error) {
console.log(error);
return res.status(500).json({ error });
}
});
NB: don't pass console.log("successful") as an argument to .json. You'll want to pass an object as argument.

Increment counters of node and ALL parents using firebase realtime db cloud functions

I'm writing cloud functions for my firebase realtime database (not firestore) using js sdk. These functions increment counters that count the number of users per area. The areas I'm using are geographical and nested (Continent>Country>Region>City). The functions are triggered by the insertion of a user into the users list of a given area (.onCreate). If a user is inserted into the users list of let's say a country, it will automatically be added to the users list of the parent continent.
After tinkering for some time I was only able to come up with a "low-level" non-scalable solution (which by the way works). This means that I need to write additionnal code if I want to add a child area to city for example.
This is a problem because I expect to add child areas in the future.
Question: Is there a way to write a generic cloud function that increments the counters of a node and the counters of all its parent nodes?
I'm quite new to firebase and any help would be really appreciated
Json structure of firebase realtime db
{
"groups" : {
"location" : {
"continents" : {
"EU" : {
"countries" : {
"DE" : {
"created" : "2019-03-25--20:03:34",
"flag" : "/flags/de.svg",
"label" : "Germany",
"level" : 2,
"regions" : {
"BE" : {
"cities" : {
"Berlin" : {
"created" : "2019-03-25--20:03:35",
"label" : "Berlin",
"level" : 3,
"type" : "location",
"usercount" : 1,
"users" : {
"rvDUa5n0oufRFGA9JB7lioom0ac2" : {
"created" : "2019-03-25--20:03:55",
"label" : "Anonymous"
}
}
}
},
"created" : "2019-03-25--20:03:35",
"label" : "Land Berlin",
"level" : 3,
"type" : "location",
"usercount" : 1,
"users" : {
"rvDUa5n0oufRFGA9JB7lioom0ac2" : {
"created" : "2019-03-25--20:03:52",
"label" : "Anonymous"
}
}
}
},
"type" : "location",
"usercount" : 1,
"users" : {
"rvDUa5n0oufRFGA9JB7lioom0ac2" : {
"created" : "2019-03-25--20:03:49",
"label" : "Anonymous"
}
}
}
},
"created" : "2019-03-25--20:03:33",
"label" : "Europe",
"level" : 1,
"type" : "location",
"usercount" : 1,
"users" : {
"rvDUa5n0oufRFGA9JB7lioom0ac2" : {
"created" : "2019-03-25--20:03:46",
"label" : "Anonymous"
}
}
}
}
}
}
}
My cloud functions for user insertion - still need to write for user deletion
exports.onUserAddToContinent = functions.database
.ref('/groups/location/continents/{continentID}/users/{userID}')
.onCreate((snapshot, context) => {
const continentId = context.params.continentID
const counterRef = admin.database().ref('/groups/location/continents/' + continentId + '/usercount');
return counterRef.transaction(usercount => {
return (usercount || 0) + 1
})
})
exports.onUserAddToCountry = functions.database
.ref('/groups/location/continents/{continentID}/countries/{countryID}/users/{userID}')
.onCreate((snapshot, context) => {
const continentId = context.params.continentID
const countryId = context.params.countryID
const counterRef = admin.database().ref('/groups/location/continents/' + continentId + '/countries/' + countryId + '/usercount');
return counterRef.transaction(usercount => {
return (usercount || 0) + 1
})
})
exports.onUserAddToRegion = functions.database
.ref('/groups/location/continents/{continentID}/countries/{countryID}/regions/{regionID}/users/{userID}')
.onCreate((snapshot, context) => {
const continentId = context.params.continentID
const countryId = context.params.countryID
const regionId = context.params.regionID
const counterRef = admin.database().ref('/groups/location/continents/' + continentId + '/countries/' + countryId + '/regions/' + regionId +'/usercount');
return counterRef.transaction(usercount => {
return (usercount || 0) + 1
})
})
exports.onUserAddToCity = functions.database
.ref('/groups/location/continents/{continentID}/countries/{countryID}/regions/{regionID}/cities/{cityID}/users/{userID}')
.onCreate((snapshot, context) => {
const continentId = context.params.continentID
const countryId = context.params.countryID
const regionId = context.params.regionID
const cityId = context.params.cityID
const counterRef = admin.database().ref('/groups/location/continents/' + continentId + '/countries/' + countryId + '/regions/' + regionId +'/cities/'+ cityId + '/usercount');
return counterRef.transaction(usercount => {
return (usercount || 0) + 1
})
})
I feel 'im missing something. There has to be a generic way of doing this.

Firebase - Get data by key or chid values - javascript

I am trying to read the data from firebase database, and display the same in a webpage.
My database structure is as below -
If you see the image, i am able to read the "UserData" using the below code -
firebase.initializeApp(config);
var database = firebase.database();
var ref = database.ref('UserData');
ref.once('value', gotData1, errData);
function gotData1(data){
//console.log(data.val());
var usrData = data.val();
var keys = Object.keys(usrData);
//console.log(keys);
for (var i = 0; i< keys.length; i++){
var k = keys[i];
var id = usrData[k].AssignedID;
var name = usrData[k].Name;
$(document).ready(function() {
var $formrow = '<tr><td>'+id+'</td><td>'+name+'</td></tr>';
$('#userInfo').append($formrow);
});
}
}
In the highlighted part of the image, you can see keys with values 196214, 196215, 196216
Now, I need to fetch the values for "One, Count" by matching the key values with available AssignedID.
How can i achieve the same?
Update, JSON as text -
{
"app_url" : "https://app_name?ls=1&mt=8",
"UserData" : {
"HNpTPoCiAYMZEeVOs01ncfGBj6X2" : {
"Name" : "Arunima Vj"
"Email" : "asd#upp.com",
"AssignedID" : 196214
},
"VXU2tdGdzZX90PJa9mpEL3zAiZo2" : {
"Name" : "Lakshman Medicherla"
"Email" : "asd#upp.com",
"AssignedID" : 196215
},
"dFlwtqDNrja2RkOySVtW106IQP62" : {
"Name" : "Prashanth Sripathi"
"Email" : "asd#upp.com",
"AssignedID" : 196216
}
}
"teams" : {
"196214" : {
"1105" : {
"One" : 7619,
"count" : 24
},
"1379" : {
"Two" : 7145,
"count" : 21
}
},
"196215" : {
"1111" : {
"One" : 7779,
"count" : 20
},
"1508" : {
"Two" : 1176,
"count" : 21
}
},
"196216" : {
"1106" : {
"One" : 7845,
"count" : 22
},
"1509" : {
"Two" : 1156,
"count" : 26
}
}
}
}
Your data structure is quite nested, which makes the code more difficult to read. But this navigates the structure generically in the minimum code I could come up with:
var ref = firebase.database().ref("/42824688");
ref.child("UserData").once('value', gotUserData);
function gotUserData(snapshot){
snapshot.forEach(userSnapshot => {
var k = userSnapshot.key;
var id = userSnapshot.val().AssignedID;
var name = userSnapshot.val().Name;
ref.child("teams").child(id).once("value", teamsSnapshot => {
teamsSnapshot.forEach(teamSnapshot => {
var teamKey = teamSnapshot.key;
teamSnapshot.forEach(teamProp => {
var prop = teamProp.key;
var val = teamProp.val();
console.log(k+" "+name+" "+id+": "+teamKey+", "+prop+"="+val);
});
});
});
})
}
So for each user, this loads the teams data for that user and then loops over the teamsSnapshot to get each teamSnapshot and then loops over that to get each team property.
Working jsbin: http://jsbin.com/noziri/edit?html,js,console

iterating tree in mongoDB

I have a collection of data like this(for example) :
{
name : "john" ,
_id : "0"
},
{
name : "Richard" ,
parent_id : "0" ,
_id : "1"
},
{
name : "Kevin" ,
parent_id : "0" ,
_id : "2"
},
{
name : "William" ,
parent_id : "1" ,
_id : "3"
},
{
name : "George" ,
parent_id : "3" ,
_id : "4"
}
I'm trying to write a function to receive an _id and return all children in any depth of this node, for example for _id = 0 I need something like this :
[
{
name : "Richard" ,
parent_id : "0" ,
depth : "1" ,
_id : "1"
},
{
name : "Kevin" ,
parent_id : "0" ,
depth : "1" ,
_id : "2"
},
{
name : "William" ,
parent_id : "1" ,
depth : "2" ,
_id : "3"
},
{
name : "George" ,
parent_id : "3" ,
depth : "3" ,
_id : "4"
}
]
I write several recursive functions to iterate on my mongodb docs but the main problem is I can't handle callbacks (asynchronous) and don't know when and how can I end the recursive function.
How can I do this with mongodb and node.js?
Any idea can be useful ,thanks.
There is a 2 famous algorithm that you can use in order to achive your goal
BFS(Breath First search) and DFS(Depth First Search).
For this problem BFS is better than DFS because you can trace your tree in O(logn)
You can use DFS too but you have to implement it in recursive way and running time will be O(n) and because your are coding in node js you have to implement it in a asynchronous and it could be a little hard to implement it.
In order to implement BFS algorithm you have to use asynchronous while loop because you have to have mongo query in your while loop and if you use normal javascript your BFS won't work because we are talking about node js not php!!!
So first this is asynchronous while loop that I use in my BFS code
function asyncLoop(iterations, func, callback ,foo) {
var done = false;
var loop = {
next: function() {
if (done) {
return;
}
if (iterations) {
func(loop);
} else {
done = true;
if(callback) callback(foo);
}
},
isEnd : function(){
return done ;
} ,
refresh : function(it){
iterations = it ;
},
break: function() {
done = true;
callback();
}
};
loop.next();
return loop;
}
And this is BFS algorithm node js code:
function bfs (_id ,callback){
_id = String(_id);
var q = [] ,res = [] ;
db.tasks.findOne({ _id : _id }).lean().exec(function(err,root){
root.depth = 0 ;
q.push(root);
asyncLoop(q.length ,function(loop){
res.push(q[0]);
db.tasks.find({ _parent : q[0]._id }).lean().exec(function(err,new_nodes){
if(err) console.log(err);
else {
var d = q[0].depth ;
q.shift();
loop.refresh(new_nodes.length + q.length);
if(new_nodes.length > 0){
new_nodes.forEach(function(new_node){
new_node.depth = d+1 ;
q.push(new_node);
});
}
loop.next();
}
});
},function(){ callback(res) });
});
}
Note:I also save depth of each query so you can have depth of each query and know where this query is in tree.

How can I get data in json array by ID

I have a problem, may you help me!
I have a json array:
"category" : [
{
id: 1,
product: [{id : product_1, type : ball}]
},
{
id : 2,
product :[{id : product_2, type : pen}]
}
]
My problem is: if i have a link such as: http://test/category/1 then , How can I do to get product information by category with id = 1 ?
Thanks for any suggestion :)
This is a way to do it in one line and without using for:
function filterById(jsonObject, id) {return jsonObject.filter(function(jsonObject) {return (jsonObject['id'] == id);})[0];}
Then if you want to get, for example, the object with id=2, you just use:
var selectedObject = filterById(yourJson['category'], 2);
And then selectedObject will get this value, as per your example:
{
id : 2,
product :[{id : product_2, type : pen}]
}
There is a downside: Old browsers, such as IE8, don't support filter() so you need to add this polyfill code for old browser compatibility:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter#Polyfill
Assuming your data structure looks like this:
var data = {
"category" : [
{
id: 1,
product: [{id : product_1, type : ball}]
},
{
id : 2,
product :[{id : product_2, type : pen}]
}
]
}
Then, you can find the item in the category array with id == 1 by searching through the array like this:
function findId(data, idToLookFor) {
var categoryArray = data.category;
for (var i = 0; i < categoryArray.length; i++) {
if (categoryArray[i].id == idToLookFor) {
return(categoryArray[i].product);
}
}
}
var item = findId(data, 1);
// item.id, item.type
If you save your array of categories in categories JS variable, you can filter this array based on simple JavaScript (with no jQuery) like that:
var result = categories.filter(function(element){
if (element.id == 2){
return true;
} else {
return false;
}
});
and then in result[0].product you will have array of products that are within specific category.
See this jsfiddle for a proof.
PS. filter() method is not available in all browsers, you may need to apply some code that will make it available if needed and not found. Here is some article on Mozilla Developers Network on the details of filter() and the code you need to make it work on old browsers: MDN: filter().
I think the OP wants to retrieve corresponding data from url.
So the first step is map the url to identifier
var urlParts = window.location.href.split(/\//)
//window.location.href = http://domain.com/category/1
// urlParts = ['http:', '', 'domain.com', 'category', '1']
var id = urlParts.pop();
var category = urlParts.pop();
Then you retrive the data from JSON string with JSON.parse:
var data = JSON.parse('{"category" : [{"id": 1, "product": [{"id" : "product_1", "type" : "ball"}] }, {"id" : 2, "product" :[{"id" : "product_2", "type" : "pen"}] } ]}');
//The data structure
// {"category" : [
// {"id": 1, "product" :
// [
// {"id" : "product_1", "type" : "ball"}
// ]},
// {"id" : 2, "product" :
// [
// {"id" : "product_2", "type" : "pen"}
// ]}
// ]}
At last, you can retrive the data similar #jfriend00's post with id and category
function findId(data, idToLookFor) {
var categoryArray = data.category;
for (var i = 0; i < categoryArray.length; i++) {
if (categoryArray[i].id == idToLookFor) {
return(categoryArray[i].product);
}
}
}
var item = findId(data.category, id);
// item.id, item.type
You might have found the answer, but if you haven't you can simply use the logical OR (||) operator.
In your case, you can use jQuery's ajax() method. To grab your product based on ids just use the below simple logic:
var prodID1 = 1, prodID2 = 2;
if(this.id == prodID || this.id == prodID2) {
//write your JSON data, etc.
//push to array, etc.
}
"category" : [
{
id: 1,
product: [{id : product_1, type : ball}]
},
{
id : 2,
product :[{id : product_2, type : pen}]
}
]
In this scenario I recommend, that you get the array from the Json response using the key. For example if your json response name is : "data" then do "data.category" which will give you an array to loop through.
Then
const allProducts = data.category;
allProducts .forEach((element) => {
//here id is your own id by which you want to compare against the json object
if (element.id == id) {
response.status(200).json(element)
//or you can return this element and capture it for any other operation you desire to do
}
});

Categories

Resources