I am using react naitve expo with firebase realtime database I have just a simple list of name, email address and score in my database I want to be able to pull the high score our so I do an order by child and I choose scores as the child and limit to first my snap shot brings back the correct entry but when I do a snapshot.key I get the child score but not the value which I want to take and add to state.
I gave tried snapshot.key.val() but that gives me null,
as does snapshot.child.val().
my databases
memory-game
{
"users" : {
"TtDcqyNkhXSUCpzHeI9jELo7DCl1" : {
"Score" : 51,
"first_name" : "Joe",
"gmail" : "watsonr#gmail.com",
"last_name" : "watson",
"locale" : "en",
"profile_picture":"https://lh5.googleusercontent.com/-616Zg1h61BA/AAAAAAAAAAI/AAAAAAAAAAA/
},
"dxuCP7if4hWFoP8iO69ndD7gOVq1" : {
"Score" : 25,
"first_name" : "jay",
"gmail" : "jayd#cmail.com",
"last_name" : "watson",
"locale" : "en",
"profile_picture" : "https://lh5.googleusercontent.com/-bzA9FCFRNqc/AAAAAAAAAAI/AAAAAAAAAAA/ACHi3re5n7l6GrqFFQK8PnySQ3cPY6T9ug/s96-c/photo.jpg"
}
}
}
firebase.database().ref("users/score").orderByChild("score").limitToFirst(1)
.once("value",snapshot =>{
const data = snapshot.key.val("score")
console.log (data)
console.log("testing")
})
Related
Making a chatbot that recommends a movie based on genre and other factors. Trying to iterate through an object retrieved from a firebase realtime database in DialogFlow. I'm using forEach but when triggered it displays "Not Available".
Preferably, the function would display a random item from the list but I have not reached that part yet - any advice on this too would be appreciated.
Below is my code.
function displayData(agent) {
return ref.orderByChild("genre1").equalTo("Comedy").on("child_added", function(snapshot) {
let obj = {};
obj = snapshot.val();
obj.forEach(function(childSnapshot) {
var childData = childSnapshot.val();
agent.add(childData.name);
});
});
}
Below is a sample database
{
"movies" : {
"movie1" : {
"genre1" : "Sci-Fi",
"genre2" : "Horror",
"name" : "Alien",
"rating" : 84,
"year" : 1979
},
"movie2" : {
"genre1" : "Comedy",
"genre2" : "Parody",
"name" : "Airplane",
"rating" : 97,
"year" : 1980
},
"movie3" : {
"genre1" : "Comedy",
"genre2" : "Teen",
"name" : "Superbad",
"rating" : 88,
"year" : 2007
}
}
}
The base problem is that the Dialogflow library requires you to return a Promise, however you're using the callback version of the call instead of the Promise version of the call. You need to change this to something more like
function displayData(agent) {
return ref.orderByChild("genre1").equalTo("Comedy").on("child_added")
.then( snapshot => {
// Do something with the snapshot
});
}
(You probably also want to use once("value") instead of on("child_added"), since you don't need updates to be sent in realtime.)
While the forEach() is probably working correctly, there is a minor problem that not all agents will return all the text that has been .add()ed. So you probably only want to call .add() once.
Since you really only want once of these children, picked randomly, you can just treat this as a JavaScript object if you have enough memory. So you could just get the keys with Object.keys(obj), pick one of the keys by random, and then get the full value of the result.
I have a problem with GiftedChat, the messages appear completely disorganized in the app and even looking for messages directly from the firebase (where it is correct), the app does not get a logical order. When sending is organized, however the problem is when you load the messages. I'm completely lost
loadMessages = async () => {
const { user } = this.props;
const matchId = this.props.navigation.getParam('matchId');
const data = (await firebase.database().ref(`matchs/${matchId}/messages`).limitToLast(300).once('value')).val();
let messages = [];
if(data){
Object.keys(data)
.forEach(messageId => {
let message = data[messageId];
if(_.get(message, 'user._id') !== user.uid) _.push(message);
messages.push(message);
});
}
this.setState(() => ({
messages,
}));
}
My JSON:
{
"-LkAMYoS3fySk46Pbpan" : {
"_id" : "f5ba3d9a-c346-4f79-b371-c5d54798567e",
"createdAt" : 1563558815857,
"text" : "First message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMZiITDxHE1WfCBGC" : {
"_id" : "c2755b48-136d-4a68-b283-377ebac7df8e",
"createdAt" : 1563558819564,
"text" : "Second message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAM_l4o_w_QeCsYRc8" : {
"_id" : "65772152-afd9-4353-b752-ac65978a536d",
"createdAt" : 1563558823838,
"text" : "Third message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMcSSTOP7L1CwyiU4" : {
"_id" : "e69f3a72-0f4e-4c06-a763-518ef1984aa0",
"createdAt" : 1563558834859,
"text" : "Fourth message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
},
"-LkAMduvBrEnUG6POGKt" : {
"_id" : "897b2042-25dc-46ec-a5f3-5bdc1fc355dd",
"createdAt" : 1563558840853,
"text" : "Fifth message",
"user" : {
"_id" : "BVY4MDwSaaSDI2bAGjwkZlYktsK2",
"avatar" : "https://firebasestorage.googleapis.com/v0/b/wefound-760f2.appspot.com/o/users%2FBVY4MDwSaaSDI2bAGjwkZlYktsK2%2Fphotos%2Fk1xuqv26wdrjxoxmp8m.jpg?alt=media&token=7c16a0e4-2cb8-45a5-83a4-635d49c71180",
"name" : "Rafael"
}
}
}
I gave console.tron.log () in the messages and they appear disorganized exactly the same is in the app, the problem is in the component?
1 - refers to the function that loads the messages.
2 - JSON file
There are two steps to ordering the data:
Telling the Firebase Database server to return the child nodes in the correct order.
Maintaining that order in your client-side code.
As far as I can tell your code does neither of these, which means the nodes end up in whatever order your client uses for JSON properties (which are by definition unordered).
Let's first see how to retrieve the data in the correct order from Firebase:
const snapshot = (await firebase.database().ref(`matchs/${matchId}/messages`).orderByChild('createdAt').limitToLast(300).once('value'));
The above orders all child nodes by the value of their createdAt property, then returns the last 300 in order to the client.
You'll note that I don't call val() here yet. The reason for that is that snapshot.val() returns a JSON object, and properties in a JSON object have no defined order. So if you call .val() too early, you lose the ordering information that the server returned.
Next up is processing them in the client-side code to not lose that order, which depends on using DataSnapshot.forEach():
data.forEach((message) => {
messages.push(message.val());
})
Finally, I am able to solve this problem by sorting the JSON which is coming to from the server based on the date and time(CreatedAT).
If the JSON data stored in a variable called discussion then your code should be
discussion.sort(function compare(a, b) {
var dateA = new Date(a.createdAt);
var dateB = new Date(b.createdAt);
return dateB - dateA;
});
In your case, data or messages is the one which holds the JSON. Add this code once you get the code in JSON format.
Thank you.
I am working on a web application that allows some users to send others push notifications. The list of users "subscribed" to any one user is stored in a firebase database, the structure is as follows;
senderUserID
senderSubscribers
subscriberOneID
token: subToken
subscriberTwoID
token: subToken
subscriberThreeID
token: subToken
Basically I need to store the list of tokens in an array in order to use each of them to specify the clients receiving a push notification.
Here is my javaScript that returns the subscriber list 'Node'. In my case senderSubscribers is actually 'players'
firebase.database().ref('/users/'+currentUserId+'/players/').once('value').then(function(snapshot){
var allPlayersNode = snapshot.val();
console.log(allPlayersNode);
});
Console.log looks something like
firstUserID:Object
regID: the first subscribers token
secondUserID:Object
regID: the second subscribers token
JSON code:
"emails" : {
"kylebehiels#hotmail" : "vlHVHcIetlZp7zS8mm6GcwoFRsB3",
"test#gmail" : "hJuVfpGTJvRyP4qsA6xyyvgQDay1"
},
"users" : {
"hJuVfpGTJvRyP4qsA6xyyvgQDay1" : {
"email" : "test#gmail.com",
"first_name" : "kyle",
"games" : {
"placeholder" : "placeholder"
},
"last_name" : "behiels",
"practices" : {
"placeholder" : "placeholder"
},
"regid" : "c_z_KWeWorU:APA91bHORVZqSph-HikfxtO2XjvMnwudIymORoSm9t3gupKZ1fFIZCLxGUbX5dsrYooHHpeEiPXhcXEMu5Eo5-nwF8bBjw-OTwSbn_rujTuPVaCDOXUKp9mzIYqeZq7SFMaWssZfyKj7",
"workouts" : {
"placeholder" : "placeholder"
}
},
"vlHVHcIetlZp7zS8mm6GcwoFRsB3" : {
"email" : "kylebehiels#hotmail.com",
"first_name" : "kyle",
"games" : {
"placeholder" : "placeholder"
},
"last_name" : "behiels",
"players" : {
"hJuVfpGTJvRyP4qsA6xyyvgQDay1" : {
"playerRegID" : "c_z_KWeWorU:APA91bHORVZqSph-HikfxtO2XjvMnwudIymORoSm9t3gupKZ1fFIZCLxGUbX5dsrYooHHpeEiPXhcXEMu5Eo5-nwF8bBjw-OTwSbn_rujTuPVaCDOXUKp9mzIYqeZq7SFMaWssZfyKj7"
},
"vlHVHcIetlZp7zS8mm6GcwoFRsB3" : {
"playerRegID" : "cvZj3hb_zkk:APA91bEcmKlDlC5VKOI6wc1BvRI5mGgmWFA3QuTR3jH48l9fz565RhY2PEXE2GkXyhKXgb67qu7ieRlWF403q6rQPi0-xgGIbfvOkhGzopfyTFLNQg7ADgNHFAd1YfwwesbHjL5IHLZd"
}
},
"practices" : {
"placeholder" : "placeholder"
},
"regid" : "cvZj3hb_zkk:APA91bEcmKlDlC5VKOI6wc1BvRI5mGgmWFA3QuTR3jH48l9fz565RhY2PEXE2GkXyhKXgb67qu7ieRlWF403q6rQPi0-xgGIbfvOkhGzopfyTFLNQg7ADgNHFAd1YfwwesbHjL5IHLZd",
"workouts" : {
"placeholder" : "placeholder"
}
}
}
}
I asked several times and nobody gives me proper answer. So in Firebase, is this the proper data structure?
{
"users" : {
"-JNNJ-0ErS6kX5AFkfM3" : {
"userUid" : "simplelogin:66",
"userId" : "66",
"email" : "fd2#sdsa.cz"
}
"accounts" : {
"-JLXe5iaH-TLSBu0RJqp" : {
"currency" : "-JLXe--zoxk1DdKa9mAT",
"description" : "account1",
"name" : "account1"
},
"-JNJdqZouwAfEzmCSHTO" : {
"description" : "asdasd",
"name" : "dsad"
},
"-JLgcjINbZni6luTuPSY" : {
"currency" : "-JLXe--zoxk1DdKa9mAT",
"description" : "fefef",
"name" : "bkkjsdds"
}
},
"categories" : {
"-JLgd4W8COP6zOlhNdq9" : {
"color" : "#c55353",
"account" : "-JLXe5iaH-TLSBu0RJqp",
"description" : "fds",
"name" : "dsfdsfds"
}
},
"records" : {
"-JNNK2hnJ99dZqRmfsjs" : {
"date" : "2005-09-28T10:48",
"amount" : 123,
"description" : "description",
"category" : "-JLgd4W8COP6zOlhNdq9"
}
}
},
}
If it's hard to read, there is explanation.
I have a user with a key. User has accounts > every account has categories (every category has a key from an account) > every category has records (every record has a key from a category.
So for example that one record (I am describing parameters):
record's key: -JNNK2hnJ99dZqRmfsjs
records belongs to category with the key: -JLgd4W8COP6zOlhNdq9
People from Firebase unfortunately didn't help me at all and I don't understand their single tutorial.
Is this the proper way to do so? I just want to have data for each user (nobody else can't see another user's data).
EDIT:
Is this correct? I know that post. But I still don't understand it.
In real world is this proper way?
users
-JNNK2hnJ99dZqRmfsjs (key of user1 for example)
name
id
etc
accounts
-JLgd4W8COP6zOlhNdq9 (key of some account)
name
description
-KFTf6W8COP6zOlhNdq9 (key of user - account belongs to user and account has users reference - the key)
Is this correct?
EDIT2:
Look at this:
awesome.firebaseio-demo.com
Anant has beautiful tree:
users
user1
name
user2
name
How did he do it? I thought I can work only with keys.
Firebase blog post - Denormalizing Your Data is Normal helps you with proper data structure.
The second question ("nobody else can't see another user's data) is about security rules - you have to determine who can read data.
Hey guys actually i got two question.
1.Im tying to get user info here is a list of what info i want (using facebook API):
user_likes, friends_about_me, user_birthday, email, user_location, user_work_history, read_friendlists, friends_groups, user_groups
here is my code for that:
Template.user_loggedout.events({
"click #fb":function(e,tmp){
Meteor.loginWithFacebook({
requestPermissions :
['user_likes',
'friends_about_me',
'user_birthday',
'email',
'user_location',
'user_work_history',
'read_friendlists',
'friends_groups',
'user_groups']
},function (err){
if(err){
console.log("error when login with facebook " + err);
} else {
console.log("login with facebook succeeded");
}
});
},
})
but my i ends up creating a user object with just some of the fields (user JSON object from mongoDB, i inserted "xxx" at some fields just for security):
{
"createdAt" : 1378842117154,
"_id" : "mW7urf5yZPCm6HhNK",
"services" : {
"facebook" : {
"accessToken" : "xxxx",
"expiresAt" : 1383945305007,
"id" : "xxxxxx",
"email" : "xxxx",
"name" : "Boaz",
"first_name" : "Boaz",
"last_name" : "xxx",
"link" : "https://www.facebook.com/xxxx",
"username" : "boazmier",
"gender" : "male",
"locale" : "he_IL"
},
"resume" : {
"loginTokens" : [
{
"token" : "TcLnp9GSbDasNZNCj",
"when" : 1378842117154
}
]
}
},
"profile" : {
"name" : "Boaz xxxx"
}
}
clearly you can see that there is no record for friends_list, user_birthday and much more.
second question:
same thing with github - i requset this: user, public_repo, avatar_url, gist
but end up with:
{
"createdAt" : 1378843359664,
"_id" : "pJGwTepYe2Ps7hhnS",
"services" : {
"github" : {
"id" : xxxx,
"accessToken" : "xxxxx",
"email" : "xxxxx",
"username" : "boazhoch"
},
"resume" : {
"loginTokens" : [
{
"token" : "hbNLcuC85MKwBJBfb",
"when" : 1378843359664
}
]
}
},
"profile" : {
"name" : "xxxx"
}
}
so i end up with no avatar but when changing my code on server to:
Accounts.onCreateUser(function(options,user){
var accessToken = user.services.github.accessToken,result,profile;
result = Meteor.http.get("https://api.github.com/user", {
params: {
access_token: accessToken
}
});
if(result.error){
throw result.error
}
profile = _.pick(result.data,
"login",
"name",
"avatar_url",
"url",
"company",
"blog",
"location",
"email",
"bio",
"html_url");
user.profile = profile;
return user;
});
my user object get the avatar_url why is that? i know that meteor ships out with Account.createUser and by doing onCreateUser im overriding it but then, what is the porpse of requestPermissions? also i can have only one Account.onCreateUser function, so how do i make this function request different data from each service? ( i want to include facebook,google,github,twitter and meetup)
Do you want the data to be available on the client to anyone with JS skills? If so, on saving things to the user record: The easiest thing to do would be to add any new information to the profile object, possibly grouped under a facebook object when from facebook. The profile object already is all published to the client. http://docs.meteor.com/#meteor_user
user.profile.prefs.color = 'red'
To keep it confidential, as you find things that should not make it to the client, write and read them from routines on the server. See
Meteor.call()
You can find code for how to get more data in the user record from the server to the client and back, where you essentially publish more. I wouldn't worry until there is a reason the profile object is insufficient.