Retrieve data from firebase resulting in undefined - javascript

I was having this problem when trying to pull from firebase. My database structure as such:
I am trying to pull the merchantName and its relevant branches details:
function getAllMerchant(){
var query = firebase.database().ref('merchants');
return query.once('value').then(data => {
var result = [];
data.forEach(snapshot => {
var merchantData = snapshot.val();
var merchantName = merchantData.merchantName;
var branchName = merchantData.branches.branchName;
var branchAddress = merchantData.branches.branchAddress;
console.log('check ' + merchantName + ' ' + branchName + ' ' + branchAddress);
result.push({merchantName: merchantName, branchName: branchName, branchAddress: branchAddress});
});
return result;
});
resolve(result);
}
However, when I printed out the branchName and branchAddress, I am getting undefined. I managed to print out merchantName though. Any ideas?
Thanks!

You're not iterating over the branches of the merchant.
data.forEach(merchantSnapshot => {
var merchantData = snapshot.val();
var merchantName = merchantData.merchantName;
console.log('check ' + merchantName);
merchantSnapshot.child("branches").forEach(brancheSnapshot => {
var branchName = brancheSnapshot.val().branchName;
var branchAddress = brancheSnapshot.val.branchAddress;
console.log(' ' + branchName + ' ' + branchAddress);
});
});

Related

Filter data obtained through GitHub API

I created this function to obtain GitHub issues:
retrieveEnerpriseIssues: function(repoOrg, repoName, callback) {
let data = null;
// token auth
octokit.authenticate({
type: 'basic',
username: config.githubEnterprise.username,
password: config.githubEnterprise.token
});
async function paginate(method) {
let response = await method({
q: "repo:" + repoOrg + "/" + repoName + " is:issue",
per_page: 100
});
data = response.data.items;
var count = 0;
while (octokit.hasNextPage(response)) {
count++;
console.log(`request n°${count}`);
response = await octokit.getNextPage(response);
data = data.concat(response.data.items);
}
return data;
}
paginate(octokit.search.issues)
.then(data => {
callback(data);
})
.catch(error => {
console.log(error);
});
}
It is called in this function which takes the issues, filters out all of the unwanted keys into json format and puts it in my db.
extractToDb: function() {
let gitIssues = null;
for(var i = 0; i < config.githubEnterprise.orgs.length; i++) {
for(var j = 0; j < config.githubEnterprise.orgs[i].repos.length; j++) {
gitHubService.retrieveEnerpriseIssues(
config.githubEnterprise.orgs[i].owner,
config.githubEnterprise.orgs[i].repos[j].repoName,
function(data, err) {
if(err) {
console.log('err: ', err);
} else {
gitIssues = data;
}
gitIssues = JSON.stringify(gitIssues);
gitIssues = JSON.parse(gitIssues);
let issueFormatForDb = null;
for(var i = 0; i < gitIssues.length; i++) {
issueFormatForDb = gitIssues[i];
const body = '{' +
'"github_id": "' + issueFormatForDb.id + '",' +
'"issue_title": "' + issueFormatForDb.title + '",' +
'"issue_number": "' + issueFormatForDb.number + '",' +
'"issue_url": "' + issueFormatForDb.url + '",' +
'"issue_state": "' + issueFormatForDb.state + '"' +
'}';
console.log('Body: ', body);
getGitHubIssues.postToDb(body);
}
});
}
}
}
I'd like to take this a step further by filtering out any issues where the state is closed. How is this done and should it be handled in my retrieveEnerpriseIssues function or my extractToDb?
Possible solution
I tried this in my extractToDb function:
gitIssues = JSON.parse(gitIssues);
gitIssues = _.where(gitIssues, {state: "open"});
let issueFormatForDb = null;
Is it the best solution or is there a better way?
As #givehug stated:
Better use _.filter, or native filter method like
gitIssues = gitIssues.filter(i => i.state === 'open')
I think .where was deprecated in later versions of lodash github.com/lodash/lodash/wiki/Deprecations. Other than that its perfectly fine.
I just realsied I can filter the state in my paginate function with this:
let response = await method({
q: "repo:" + repoOrg + "/" + repoName + " is:issue" + " label:issue_label" + " state:open",
per_page: 100
});

Array empty after pushes were made in get request in Node.js/Express

I am writing a function calling an API to fetch URLs. These are the steps that I wish to accomplish:
Parsing in an array of objects (restaurants) as arguments
For each object, call the Google Search API to get some imageURLs
Store those imageURLs in an array
Add imageURLs as an attribute called imageURLs to each object within the array in the argument
The code is able to log the imageURLs within the GET request, but outside of the request, imageURLs is just an empty array.
var googleSearch = function(restaurants, cb){
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
Array.from(restaurants).forEach(function(restaurant){
var keyWord = restaurant.name + " "+ restaurant.location.city
+ " "+ restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key="+ apiKey +
"&q="+ keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
//image URLs of each restaurants to be displayed in the front end
var imageURLs = [];
request
.get(googleURL,
{
json : true, headers: {
'User-Agent' : 'thaorell'
}
})
.then(function(response){
Array.from(response.items).forEach(function(item){
imageURLs.push(item.link)
});
})
.catch(e => {
console.log(e);
})
restaurant.imageURLs = imageURLs
})
cb(null, restaurants);
}
You're misunderstanding the Promise API:
var googleSearch = function (restaurants, cb) {
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
return Promise.all(Array.from(restaurants).map(function (restaurant) {
var keyWord = restaurant.name + " " + restaurant.location.city
+ " " + restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key=" + apiKey +
"&q=" + keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
return request
.get(googleURL,
{
json: true, headers: {
'User-Agent': 'thaorell'
}
}
)
.then(function (response) {
restaurant.imageURLs = Array.from(response.items).map(function (item) {
return item.link;
});
return restaurant;
})
})
)
.then(restaurants2 => cb(null, restaurants2))
.catch(cb)
}
As you can see you need to wait for all of the requests to finish before you pass the data back to the callback.

Updating object in Firebase based on a if condition

I'm trying to update an object in Firebase only if one of his property doesn't exist.
The logic so far is : you loop over photos of a defined trip, and if in this photo you don't find the property "location", you update the object by inserting the property "location" (which itself is an object with properties "coord", "locationname", "regioncode", "thumbnailurl").
The problem is that after I load the page, the object "location" is not inserted for photos which don't have the property "location".
My database structure :
My JS :
db.ref('photos/' + owneruid + '/trips/' + tripuid).once('value').then(snap => {
var photos = snap.val()
for (var key in photos) {
console.log('Photo ID is ' + key)
var thisPhoto = photos[key]
this.photos.push(thisPhoto)
var hasLocation = 'location';
if(photos[key].hasOwnProperty(hasLocation)){
console.log("location exists")
}
else{
console.log("NO LOCATION")
var location = {coord:"", locationname:"", regioncode:"", thumbnailurl:""}
function writeLocation(location) {
db.ref('photos/' + owneruid + '/trips/' + tripuid + thisPhoto).update(location)
}
this.photos.push(thisPhoto)
}
}
this.photosDataIsReady = true
})
As we can see in the console, the if condition in the loop works:
Try this code
db.ref('photos/' + owneruid + '/trips/' + tripuid).once('value').then(snap => {
var photos = snap.val()
for (var key in photos) {
console.log('Photo ID is ' + key)
var thisPhoto = photos[key]
this.photos.push(thisPhoto)
var hasLocation = 'location';
if(photos[key].hasOwnProperty(hasLocation)){
console.log("location exists")
}
else{
console.log("NO LOCATION")
var location = {coord:"", locationname:"", regioncode:"", thumbnailurl:""}
db.ref('photos/' + owneruid + '/trips/' + tripuid + thisPhoto).update(location);
this.photos.push(thisPhoto)
}
}
this.photosDataIsReady = true
})

async function inside a for loop

Hi i´m trying to convert sqlite database to NeDb, with this code:
const sqliteJSON = require('sqlite-json');
const Datastore = require('nedb')
const exporter = sqliteJSON('etecsa.db');
db = new Datastore('etecsa.nedb');
db.loadDatabase();
tables = ['fix','movil'];
tables.forEach(function(table) {
sql = 'select count(1) from ' + table;
exporter.json(sql, function (err, json) {
toNeDB(table, JSON.parse(json)[0]['count(1)'])
});
}, this);
var toNeDB = function(table, count) {
var inc = 10000;
console.log(table + ' => ' + count)
for (var i = 0; i < count + inc; i += inc) {
var sql = 'SELECT * FROM ' + table + ' ORDER BY province ASC, number DESC LIMIT '+ i + ' , ' + inc;
console.log(i)
exporter.json(sql, function(err, json) {
var data = JSON.parse(json);
db.insert(data, function (err, newDoc) {});
});
}
}
the problem is that the for loop its not working as I desire. I need to use it to change the sql pagination because the sqlite database is very huge and I can´t pass all the data on a single query.
UPDATE using async.map
const sqliteJSON = require('sqlite-json');
const Datastore = require('nedb')
var range = require("range");
var async = require("async");
const exporter = sqliteJSON('etecsa.db');
db = new Datastore('etecsa.nedb');
db.loadDatabase();
tables = ['fix','movil'];
tables.forEach(function(table) {
sql = 'select count(1) from ' + table;
exporter.json(sql, function (err, json) {
toNeDB(table, JSON.parse(json)[0]['count(1)'])
});
}, this);
var toNeDB = function(table, count, cb) {
var inc = 10000;
var pagination = range.range(1,count+inc,inc)
async.map(pagination, function (page, cb){
var sql = 'SELECT * FROM ' + table + ' ORDER BY province ASC, number DESC LIMIT '+ page + ' , ' + inc;
console.log(page, table, inc);
exporter.json(sql, function(err, json) {
var data = JSON.parse(json);
console.log(data[0])
db.insert(data, function (err, newDoc) {});
});
}.bind({ table: table, inc: inc }), function(err,results){
})
}
and the output:
1 'fix' 10000
10001 'fix' 10000
....
1150001 'fix' 10000
1 'movil' 10000
10001 'movil' 10000
...
3730001 'movil' 10000
{ number: '8775031',
name: 'UNION ELECTRICA',
address: 'S ALLENDE #666 OQUENDO SOLEDAD',
province: 7 }
{ number: '8734454',
name: 'EMP ESTB ESP Y SERVICIOS',
address: 'ESAPDA #256 CONCORDIA S LAZARO',
province: 7 }
If you need to know when each action occurred, you should put the console.log inside the callback.
Something like that:
var toNeDB = function(table, count) {
var inc = 10000;
console.log(table + ' => ' + count)
for (var i = 0; i < count + inc; i += inc) {
var sql = 'SELECT * FROM ' + table + ' ORDER BY province ASC, number DESC LIMIT '+ i + ' , ' + inc;
exporter.json(sql, (function(i) {
return function(err, json) {
console.log(i)
var data = JSON.parse(json);
db.insert(data, function (err, newDoc) {});
}
})(i));
}
}
You could use recursion instead of a loop, that way you would be sure the next iteration won't execute until the first is done.
var proc = function (i, count, table) {
var sql = 'SELECT * FROM ' + table + ' ORDER BY province ASC, number DESC
LIMIT ' + i + ' , ' + inc'
console.log(i)
exporter.json(sql, function (err, json) {
var data = JSON.parse(json)
db.insert(data, function (err, newDoc) {
if (i < count) {
i += inc
proc(i, count, table)
}
})
})
}
var toNeDB = function (table, count) {
var inc = 10000
console.log(table + ' => ' + count)
proc(0, count, table)
}
let me know if that works

Can googlechart query more than 1 spreadsheet at the same time?

because I tried query 3 sheets with 3 charts at the same time with 1 handle function ,it works but the result is wrong (it display the same chart in 3 div)
So I think I have to add handle function on each chart like
google.charts.load('current', {packages: ["geochart"]});
google.charts.setOnLoadCallback(drawRegionsMap);
function drawRegionsMap() {
var query1 = new google.visualization.Query("https://docs.google.com/spreadsheets/d/14VouG7zZqHGB9CA6bxQx6CXX-TvOYkSqTmrN5DAj1Do/edit#gid=1175123524");
var query2 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1RsugJPtz2EdHOLaiL0SvR9bh61H-vAgn9x1QBjIJ--c/edit?usp=sharing');
var query3 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1zPP22gUPLDqTrvASIU3OXpmeHL_9IBS2O4z75g-1BHY/edit?usp=sharing');
query1.send(handleQueryResponseTR1);
query2.send(handleQueryResponseTR2);
query3.send(handleQueryResponseTR3);
}
function handleQueryResponseTR1(response1) {
if (response1.isError()) {
alert('Error in query: ' + response1.getMessage() + ' ' + response1.getDetailedMessage());
return;
}
function handleQueryResponseTR2(response2) {
if (response2.isError()) {
alert('Error in query: ' + response2.getMessage() + ' ' + response2.getDetailedMessage());
return;
}
function handleQueryResponseTR3(response3) {
if (response3.isError()) {
alert('Error in query: ' + response3.getMessage() + ' ' + response3.getDetailedMessage());
return;
}
var data1 = response1.getDataTable();
var data2 = response2.getDataTable();
var data3 = response3.getDataTable();
but I got an error
handleQueryResponseTR2 is not defined
So I don't know if google chart can query more than 1 sheet in one page?
I don't believe googlechart queries have any problems with multiple queries at the same time, to answer the question.
Regarding your code:
Your handleQueryResponseTR2 function is a local function in handleQueryResponseTR1 but you try to call it from drawRegionsMap(). handleQueryResponseTR2() is not defined in that scope.
Move handleQueryResponseTR2() to upper scope to make it visible to the calling function.
In fact, move all your handleQueryResponse functions to the upper level.
var data1;
var data2;
var data3;
function handleQueryResponseTR1(response1) {
if (response1.isError()) {
alert('Error in query: ' + response1.getMessage() + ' ' + response1.getDetailedMessage());
return;
}
data1 = response1.getDataTable();
}
function handleQueryResponseTR2(response2) {
if (response2.isError()) {
alert('Error in query: ' + response2.getMessage() + ' ' + response2.getDetailedMessage());
return;
}
data2 = response2.getDataTable();
}
function handleQueryResponseTR3(response3) {
if (response3.isError()) {
alert('Error in query: ' + response3.getMessage() + ' ' + response3.getDetailedMessage());
return;
}
data3 = response3.getDataTable();
}
function drawRegionsMap() {
var query1 = new google.visualization.Query("https://docs.google.com/spreadsheets/d/14VouG7zZqHGB9CA6bxQx6CXX-TvOYkSqTmrN5DAj1Do/edit#gid=1175123524");
var query2 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1RsugJPtz2EdHOLaiL0SvR9bh61H-vAgn9x1QBjIJ--c/edit?usp=sharing');
var query3 = new google.visualization.Query('https://docs.google.com/spreadsheets/d/1zPP22gUPLDqTrvASIU3OXpmeHL_9IBS2O4z75g-1BHY/edit?usp=sharing');
query1.send(handleQueryResponseTR1);
query2.send(handleQueryResponseTR2);
query3.send(handleQueryResponseTR3);
}
Please, note that the handleQueryResponse functions are called asynchronously when the responses are received.

Categories