i am newbie to nodejs/javascript and trying to pass a value from a function.
Below is my request.on function ( i need to get favoriteStn value and pass it on while building the JSON array)
response.on('end', function () {
str = JSON.parse(str);
var summariesJSON = str[0].summaries
var resToSend = [];
for(var i in summariesJSON) {
var item = summariesJSON[i];
var favoriteStn = findifFavorite (usernameFrmQuery,item.device_id,function(value){
favoriteStn = value;
});
resToSend.push({
"lat" : item.lat,
"lng" : item.ln,
"count" : item.count,
"status" : item.status,
"id" : item.id,
"name" : item.name,
"address" : item.address,
"favoriteStn" : favoriteStn,
"fav_count" : findFavCount
});
}
res.send(resToSend);
});
function findifFavorite (username,stationId,cb) {
var options = {
};
ddb.getItem(chgStationfavorite, username, String(stationId), options, function(err, getitemRes, cap) {
if (err) {
cb("Failure" + err);
} else if(typeof(getitemRes) != 'undefined'){
cb("Y");
}
else {
cb("N");
}
});
}
issue is i dont get anything created for favoriteStn, i know it is getting into the function and providing values as i can see it thru console.log
can you help me on how i need to use callback and get it working?
you have to consider everything in node.js is asynchronous.
in your case findifFavorite execution time is taking more time and the value is not available for the array.
this is how you can fix your code, you have to move the resToSend array in the callback function.
Start reading more about promises
https://github.com/petkaantonov/bluebird
so you will not get stuck in callback hell.
var favoriteStn = findifFavorite (usernameFrmQuery,item.device_id,function(value){
favoriteStn = value;
resToSend.push({
"lat" : item.lat,
"lng" : item.ln,
"count" : item.count,
"status" : item.status,
"id" : item.id,
"name" : item.name,
"address" : item.address,
"favoriteStn" : favoriteStn,
"fav_count" : findFavCount
});
res.send(resToSend);
});
Related
I'm gonna do my best to explain this as I'm new to using javascript along with Firebase SDK. Here is the mock data I have:
"Via" : {
"00zz00" : {
"coordinates" : "0,0",
"order_number" : 1,
"route_id" : "xyz987",
"via_id" : "00zz00"
},
"1a2b3c" : {
"coordinates" : "10,-10.1",
"order_number" : 1,
"route_id" : "abc123",
"via_id" : "1a2b3c"
},
"2b3c4d" : {
"coordinates" : "45.5,-24.7",
"order_number" : 2,
"route_id" : "abc123",
"via_id" : "2b3c4d"
},
"3c4d5e" : {
"coordinates" : "45.8,-24.0",
"order_number" : 4,
"route_id" : "abc123",
"via_id" : "3c4d5e"
},
"4d5e6f" : {
"coordinates" : "20.0,-20.0",
"order_number" : 3,
"route_id" : "abc123",
"via_id" : "4d5e6f"
}
}
I first made a query using .on() with the "child_added" event to fill an array with the coordinates of every result:
var waypoints = new Array();
var refVia = firebase.database().ref("Via");
refVia
.orderByChild("route_id")
.equalTo("abc123")
.on("child_added", function (snapshot) {
waypoints.push(snapshot.val().coordinates);
});
I am calling another API and using the array to create a route and I realized I was getting an error since my array was still empty. I found a solution on here mentioning using .once().then() with the "value" event along with a promise but I'm a bit confused about how to go from here. I tried this but I'm a bit lost from here.
var refVia = firebase.database().ref("Via");
return refVia
.orderByChild("route_id")
.equalTo("abc123")
.once("value")
.then(
function (snapshot) {
var via = [];
//Not sure what to do here to add the entries to my array...
return Promise.all(via);
},
function (error) {
console.error(error);
}
);
I understand that you need to iterate over the keys of the nodes (which are equal to the via_id subnode values) in order to define promises that you add to the via Array. So the following should do the trick:
var refVia = firebase.database().ref('Via');
return refVia
.orderByChild('route_id')
.equalTo('abc123')
.once('value')
.then((snapshot) => {
const via = [];
for (const [key, value] of Object.entries(snapshot.val())) {
console.log(`${key}: ${value.via_id}`);
via.push(*** here build the Promise based on the key value ***)
// example with Axios https://github.com/axios/axios
via.push(axios.get('https://..../via?ID=' + key));
}
return Promise.all(via);
})
.then(results => {
// results is an Array of results of each call to the API
// For example
results.forEach(r => {
// ...
})
})
.catch((error) => {
console.error(error);
});
I'm trying to gain an understanding of query in Firebase. I want to pass userId A & B and find out if they are subscribed to a common chatId, it will either return true or false.
How can query both userId and evaluate results for my desired output?
export const checkForExistingChat = (currentUserId, recipient) => {
var IdList = {}
var query = database
.ref(`Chats/${currentUserId}`)
.orderByChild("subscribedToChat")
.once("value", function (dataSnapshot) {
dataSnapshot.forEach(function (childSnapshot) {
const childData = childSnapshot.val();
console.log("childData : ", childData);
});
});
};
Export JSON of Chat
"Chats" : {
"61vtPjp8YVVSzpvexwXMgEHghYf1" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"2d718ea7-eafa-48db-af14-f165f07b3b08" : "2d718ea7-eafa-48db-af14-f165f07b3b08",
"2e4fd8bb-4afb-4229-83ec-5a427fe2731d" : "2e4fd8bb-4afb-4229-83ec-5a427fe2731d",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118",
"3a816ac1-6e97-4d66-ae19-77e65f8c2df4" : "3a816ac1-6e97-4d66-ae19-77e65f8c2df4",
}
},
"qqpBNbEa8ZSiCEUlseFeGeiRqzh2" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118"
}
}
}
Since you already know how to load data from Firebase, this is essentially a non-Firebase problem: finding the overlapping keys in two lists of keys.
A quick code snippet:
var json = {
"Chats" : {
"61vtPjp8YVVSzpvexwXMgEHghYf1" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"2d718ea7-eafa-48db-af14-f165f07b3b08" : "2d718ea7-eafa-48db-af14-f165f07b3b08",
"2e4fd8bb-4afb-4229-83ec-5a427fe2731d" : "2e4fd8bb-4afb-4229-83ec-5a427fe2731d",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118",
"3a816ac1-6e97-4d66-ae19-77e65f8c2df4" : "3a816ac1-6e97-4d66-ae19-77e65f8c2df4",
}
},
"qqpBNbEa8ZSiCEUlseFeGeiRqzh2" : {
"subscribedToChat" : {
"1a555cbf-30b7-4c8f-9986-4252a7620c45" : "1a555cbf-30b7-4c8f-9986-4252a7620c45",
"35c537ef-57dd-48c5-9350-5d1fe2e9d118" : "35c537ef-57dd-48c5-9350-5d1fe2e9d118"
}
}
}
};
var keys1 = Object.keys(json.Chats["61vtPjp8YVVSzpvexwXMgEHghYf1"].subscribedToChat);
var keys2 = Object.keys(json.Chats["qqpBNbEa8ZSiCEUlseFeGeiRqzh2"].subscribedToChat);
console.log(keys1, keys2);
var commonKeys = keys1.filter(function(key) {
return keys2.indexOf(key) >= 0;
});
console.log(commonKeys);
This is an O(n^2) algorithm, but I doubt that'll be a concern on the list sizes you're likely to have. If it is a concern, and the lists are sorted, you can keep a cursor in each least, and move forward only through them once to make it an O(2n) algorithm.
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
So i'm trying to replace fields on the data queried from the database in sails.
async.waterfall( [
function getscores(callback) {
Score.find({course : courseId}).paginate({page : 1 , limit: 10}).populate('course')
.exec(function(err,data) {
callback(null,data);
});
}
, function addUserInfo(result,callback) {
for(var i=0; i < result.length; i++){
result[i].user = User.findOne({id : result[i].user}).exec(function(err,data) {
var temp = {
"name" : data.name,
"id" : data.id,
"user_id" : data.user_id
}
return temp;
});
}
res.json(messageGenerator(200, 'Sucecss', result));
}],function(err) {
console.log(err);
}
);
the first function 'getScores' returns the scores array but each score property only has a user id. Now in addUserInfo function, i want to be able to add the user's name to the score property.
But the above code fails to return the users inside. the user property of score is empty. i believe the response is already sent before the program gets to add the user property ( due to asyncronousness of the database adapter).
Following a brief comment chat, the following replacement for the addUserInfo function should help you achieve what you desire:
function addUserInfo(results,callback) {
async.map(results, function(result, callback) {
User.findOne({id : result.user}).exec(function(err, data) {
callback(err, Object.assign(result, {
"user": {
"name" : data.name || null,
"id" : data.id || null,
"user_id" : data.user_id || null
}
}));
});
}, function(err, output) {
return res.json(messageGenerator(200, "Success", output))
});
}
Async map allows us to asynchronously iterate over results, allowing us to amend the result by supplying the callback with the new result as the second parameter. The Final function is our final callback, that gets provided with any err's that have occured along the way and our new Array as output.
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.