Firebase trouble reading lists - firebase

The tutorial I'm following here https://www.firebase.com/tutorial/#tutorial/basic/5 says that for lists you can push a new item like this...
var myDataRef = new Firebase("https://.../items"
myDataRef.push({name: "Sally"});
The docs say here https://www.firebase.com/docs/managing-lists.html that to read list data just do something like this
myDataRef.on('value', function(snapshot) {
console.log(snapshot.val());
});
snapshot.val() gives back an object with random keys that contain my objects. Do I really have to do something like
arr =[] Object.keys(snapshot.val()).forEach(function(key) { arr.push(snapshot.val()[key])})
to get a normal looking array of objects? or am I missing something here.. Thanks a ton.

I'm not entirely sure what you're asking, but see if this helps to retrieve the data you're looking for with snapshot.val().Use child_added, this will go down the endpoint("firebase_url/items") and show each immediate object.
myDataRef.on('child_added', function(snapshot) {
console.log(snapshot.val());
});
Check out this link to get more info on reading from firebase, http://www.firebase.com/docs/reading-data.html

JavaScript objects are not ordered. So the keys may appear in different order than your data (JSON can put them anywhere it pleases). To iterate them in order, try forEach:
myDataRef.on('value', function(snapshot) {
snapshot.forEach(function(ss) {
console.log(ss.name());
});
});
For more real-time results, Ron's example using child_added is ideal.

Related

How do i query a Firebase database for a nested property?

Hi i have a noSql db in firebase.
I want to get the object where userId is 288
i'v tried many combinations but i cant figure out how its done.
This is my code so far :
var refTest= database.ref('conversation')
var query = refTest
.orderByChild('messages');
query.on('value', function(data) {
var a = data.val();
console.log(a.messages.userId);
console.log(data.val());
});
This is a image of my "schema"
I'm obviously a noob when it comes to NoSQL. I do understand SQL
All help is appreciated
You can order/filter on a nested value like this:
var refTest= database.ref('conversation')
var query = refTest.orderByChild('messages/userId').equalTo("288");
query.on('value', function(snapshot) {
snapshot.forEach(function(child) {
console.log(child.key);
console.log(child.val());
});
});
The forEach is needed, since there may be multiple child nodes with messages/userId equal to 288.
The key named "messages" doesn't make sense in your schema. Because if you want to have another message under that conversation, then you wouldn't be able to add it with the same key name and you also couldn't add it under "messages" because it would overwrite the other one. My suggestion is to use the push() method for adding a new message. This way you uniquely identify each message.
Regarding your question, an easy to understand way of parsing your schema is this: you loop through each message of each conversation for finding the messages with userID.
refTest.on('value', function(data) {
var conversations = data.val();
for (conversation in conversations){
for (message in conversation) {
if (message.userId == 288) {
// do whatever you need
// and eventually return something to break the loops
}
}
}
}
Of course, you can adapt it based on your needs

Cloud Functions retrieve List from Firebase Database

I'm triggering a Cloud Function using Http Request.
The issue is to retrieve the entire List of Objects I have, without an event to then loop through them.
The List is under the account/userId Node.
Here is what I use but I get nothing:
return admin.database().ref('/account/' + userId).once('value').then(function (snap) {
let data = snap.val();
}
Without seeing your database structure it is a bit difficult to write an answer and be 100% sure it is a correct one, but the following should do the trick:
return admin.database().ref('/account/' + userId).once('value').then(function (snap)
snap.forEach(function(child) {
const childKey = child.key; // <- here you get the key of each child of the '/account/' + userId node
console.log(childKey);
const childVal = child.val(); // <- and here you get the values of these children as JavaScript objects
console.log(childVal);
});
});
In case this is not exactly what you are looking for, please update you Question with your database structure and the entire code of your Cloud Function.

Meteor Dashboard and publication/subscription

EDIT: as the original question was too vague I have updated it to make it more concrete
I'd like to create a dashboard in Meteor that shows some statistics about my collections (e.g. how many docs, how many users...). I have been trying the past days but can't seem to find a good/intelligent way.
I initially just did the following:
Template.dashboard.helpers({
getProductsCount: function() {
return Products.find().count();
}
});
This did not work. I think because it counts the number of products from minimongo, but not sure.
Then I did the following:
In the template helper, call a method and get the value to show on the dashboard page (does not work)
Was told not to use pub/sub mechanism for this type of metric
Worked via Session variables (did work, but feels a bit strange to store this kind of metric data in Session variables
So then I read in another SO response about Reactive Variables and tried the following:
Template.dashboard.helpers({
getProductsCount: function() {
return Template.instance().myAsyncValue.get();
}
});
Template.dashboard.created = function() {
var self = this;
self.myAsyncValue = new ReactiveVar("Waiting for response from server");
Meteor.call('getProductsCount', function(error, asyncValue){
if (error)
console.log(error);
else
self.myAsyncValue.set(asyncValue);
});
};
This works, but I find this extremely difficult for something as simple as showing a product count (or any other metric). Not sure I understand the reason why I should use sth as reactive variables?
Then -out of curiosity- I tried the following (using meteor add simple:reactive-method) and it works:
Template.customerDashboard.helpers({
getProductsCount: function () {
return ReactiveMethod.call("getProductsCount");
}
});
So the question really is why having to use Reactive variables and methods for sth as simple as this. Can someone explain?
If you want to show the count only in the view, the best way is to return the count number only. you do not need publish/subscribe at all. you can use server methods. and if you want to show data also, you can go for pub-sub. and your approach is correct.

How to remove data that was pushed in a list in Firebase?

Given
var messageListRef = new Firebase('https://SampleChat.firebaseIO-demo.com/message_list');
messageListRef.push({ 'user_id': 'fred', 'text': 'Yabba Dabba Doo!' });
How to remove that added data { 'user_id': 'fred', 'text': 'Yabba Dabba Doo!' } later from Firebase? Is there a clean and simple way to do that?
I would like to be able to find that data again later and then remove it, assuming I don't know the unique id generated, I can't do new Firebase('https://SampleChat.firebaseIO-demo.com/message_list/'+uniqueId).remove() (and I don't know if this is the good practice). In my idea I would first query the data but I don't know how I can do that with a list of data. For example, I would like to be able to remove that data onDisconnect.
On that page https://www.firebase.com/docs/web/api/firebase/push.html, it seems the "See Lists of Data" is not yet written. Is it in the roadmap to add such remove for lists of data?
When you call push it returns the new node. So you could keep a list of messages the user added in memory:
var myMessageKeys = []; // put this somewhere "globally"
And then whenever you add a message:
var newMessageRef = messageListRef.push({ 'user_id': 'fred', 'text': 'Yabba Dabba Doo!' });
myMessageKeys.push(newMessageRef.key());
Personally this feels hacky to me. I would prefer to use a query, so that for example if fred disconnects you'd do something like:
var myMessages = messageListRef.orderByChild('user_id').equalTo('fred');
myMessages.on('value', function(messagesSnapshot) {
messagesSnapshot.forEach(function(messageSnapshot) {
messageSnapshot.ref().remove();
});
});
So figuring out which messages to remove is the trick. But suppose you want to delete by user id; perhaps when Fred disconnects, you want to remove all of his messages. You could find and delete them like this:
var query = messageListRef.orderByChild('user_id').equalTo('Fred');
query.once('child_added', function(snapshot) {
snapshot.forEach( function(msg) {
msg.ref().remove();
});
});

firebase retrieve data by using orderByKey() and equalTo()

So I'm trying to find the data "aaaaabbbbbbaaaa" in this structure:
disney
studentList
-Jh46tlaNFx_YmgA8iMJ: "aaaaabbbbbbaaaa"
-Jh474kAvoekE4hC7W3b:"54ce1cbec4335cd3186105dc"
I used this
var ref = new Firebase("https://disney.firebaseio.com/");
ref.child("studentList").orderByKey().equalTo("54ca2c11d1afc1612871624a").on("child_added", function(snapshot) {
console.log(snapshot.val());
});
But I got nothing back. What was wrong?
What should I use?
In the data sample that you've given, there is no node under studenList with a key of 54ca2c11d1afc1612871624a.
Your keys are -Jh46tlaNFx_YmgA8iMJ and -Jh474kAvoekE4hC7W3b. You can easily determine this yourself by:
ref.child("studentList").orderByKey().on("child_added", function(snapshot) {
console.log(snapshot.key()); // on newer SDKs, this may be snapshot.key
});
You seem to want to order the nodes by their value, but that is not an operation that is available on Firebase at the moment. Firebase can only query children by a value of a named property, the key or its priority. So if you'd change the data structure to:
disney
studentList
-Jh46tlaNFx_YmgA8iMJ:
name: "aaaaabbbbbbaaaa"
-Jh474kAvoekE4hC7W3b:
name: "54ce1cbec4335cd3186105dc"
You could get the children order by name with:
ref.child("studentList")
.orderByChild("name")
.equalTo("54ca2c11d1afc1612871624a")
.on("child_added", function(snapshot) {
console.log(snapshot.val());
});
Just a side node: if your actual node values are like the ones in the sample you provided, you might want to consider using the values as the keys; they already seem pretty unique to my untrained eye.
I guess it was added after your question was made, the solution here https://firebase.google.com/docs/database/admin/retrieve-data?hl=en#ordering-by-value tackles your need right away:
ref("studentList").orderByValue().on("value", function(snapshot) {
snapshot.forEach(function(data) {
console.log(data.val());
});
});

Resources