Noob here.
Trying to see if a DatabaseReference exists in my database. Here is how I do it:
String key = "ABCDE";
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("itemIds").child(key);
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snap) {
if (!snap.exists())
tellUserThatItDoesntExists();
else
tellUserThatItExists();
}
.....
}
But the code always results to the reference not existing even though a node root/itemIds/ABCDE (which is BTW, I added through the Firebase console) does exist in the database.
All of the data is public, so there is no reason for me to not be allowed to read data.
Edit: Here is a screenshot of the visual tree of the database. Everything here (except the meh node) was saved using Firebase console:
Another edit: Did some fiddling around and apparently, based on my observation, Firebase can't seem to read data that were added by the console. I have come up with this conclusion because I made the program I'm working on write something to the database and tried to check if that exists and it works fine.
Any idea on how to solve this issue?
Ok so the reason for this error is obvious from your snapshot.
Don't save data with - " " quotes! Firebase reads the data added from console just fine. But if you are adding quotes then you have to refer as - .child(""itemIds"")
Hope this helps. Remove the quotes and firebase will read it. Only the value for key can have quotes. Check the meh node how it is formatted. That is the correct way.
Related
This question already has an answer here:
How to create auto incremented key in Firebase?
(1 answer)
Closed 4 years ago.
I want to append a String to my List on the Firebase Realtime Database.
(My code already works but there is a problem)
So the Database looks like this:
message:
0: "some string"
1: "another string"
2: "some string"
But I think the problem with this code would be, that if somebody reads the numbers of messages and then wants to write a message there would be a problem, when another user writes a message in the mean time (because the number of messages would change).
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("message");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myRef.child(
String.valueOf(dataSnapshot.getChildrenCount())
).setValue("SOME STRING");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Trying to use sequential numeric indexes (also often referred to as array indexes or auto-increment values) in a multi-user Firebase is an anti-pattern for a few reasons.
As you've already noted yourself, there's a chance of users overwriting each other's data. This is fixable however by using a transaction, which is the way to go if you need to property a value based on its existing value. The reference documentation for the JavaScript DatabaseReference.transaction method have this example that is pretty much what you need:
// Increment Ada's rank by 1.
var adaRankRef = firebase.database().ref('users/ada/rank');
adaRankRef.transaction(function(currentRank) {
// If users/ada/rank has never been set, currentRank will be `null`.
return currentRank + 1;
});
The syntax in Android is slightly more involved, but would work the same.
While a transaction works, this means that the application will only work when the user is connected to the server. When they're offline, the transaction will fail.
For these reasons Firebase apps typically use a different mechanism to generate their keys. The built-in push() method of the API generates a unique, always-incrementing key. While this key is not as readable as your sequential, numeric keys, they do address both of the above problems without the need for you to write more code for it yourself. With push() adding a message becomes as simple as:
final DatabaseReference myRef = database.getReference("message");
myRef.push().setValue("SOME STRING");
Note that this topic has been covered quite a bit already, so I recommend also checking out:
Best Practices: Arrays in Firebase
The 2^120 Ways to Ensure Unique Identifiers
How to create auto incremented key in Firebase?
Auto-increment a value in Firebase (has the transaction code for Android)
how do i auto increment a value in firebase
This is my first post here so sorry for any confusion!
I recently started using Flutter and I'm new to Firebase too.
I'm using a realtime database as the backend for my app, and I've got a hierarchy that looks like:
What I want to do is lookup a specific user by their id, fetch their information (gender and name in this case) and then set a widget (in this case a text widget) to use that value.
How can this be accomplished?
I've searched through a lot of StackOverflow questions about this, and all of them use FutureBuilders or DataSnapshots and I can't quite work out how to go about sorting them out so they work.
All of the tutorials online also don't get info from a specific user and instead query the entirety of the database.
You can do the following:
db = FirebaseDatabase.instance.reference().child("Users");
db.orderByKey().equalTo(Id).once().then((DataSnapshot snapshot){
Map<dynamic, dynamic> values = snapshot.value;
values.forEach((key,values) {
print(values["name"]);
});
});
First, you get an instance to the node User, and then using orderByKey() you can search the user by the id, and retrieve the name and gender.
Check the link following for more information:
https://github.com/flutter/plugins/blob/master/packages/firebase_database/lib/src/query.dart#L183
This question already has an answer here:
How to create auto incremented key in Firebase?
(1 answer)
Closed 4 years ago.
I want to append a String to my List on the Firebase Realtime Database.
(My code already works but there is a problem)
So the Database looks like this:
message:
0: "some string"
1: "another string"
2: "some string"
But I think the problem with this code would be, that if somebody reads the numbers of messages and then wants to write a message there would be a problem, when another user writes a message in the mean time (because the number of messages would change).
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("message");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myRef.child(
String.valueOf(dataSnapshot.getChildrenCount())
).setValue("SOME STRING");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Trying to use sequential numeric indexes (also often referred to as array indexes or auto-increment values) in a multi-user Firebase is an anti-pattern for a few reasons.
As you've already noted yourself, there's a chance of users overwriting each other's data. This is fixable however by using a transaction, which is the way to go if you need to property a value based on its existing value. The reference documentation for the JavaScript DatabaseReference.transaction method have this example that is pretty much what you need:
// Increment Ada's rank by 1.
var adaRankRef = firebase.database().ref('users/ada/rank');
adaRankRef.transaction(function(currentRank) {
// If users/ada/rank has never been set, currentRank will be `null`.
return currentRank + 1;
});
The syntax in Android is slightly more involved, but would work the same.
While a transaction works, this means that the application will only work when the user is connected to the server. When they're offline, the transaction will fail.
For these reasons Firebase apps typically use a different mechanism to generate their keys. The built-in push() method of the API generates a unique, always-incrementing key. While this key is not as readable as your sequential, numeric keys, they do address both of the above problems without the need for you to write more code for it yourself. With push() adding a message becomes as simple as:
final DatabaseReference myRef = database.getReference("message");
myRef.push().setValue("SOME STRING");
Note that this topic has been covered quite a bit already, so I recommend also checking out:
Best Practices: Arrays in Firebase
The 2^120 Ways to Ensure Unique Identifiers
How to create auto incremented key in Firebase?
Auto-increment a value in Firebase (has the transaction code for Android)
how do i auto increment a value in firebase
I am making a challenges between users in my app .I am trying to get the last 15 users who enters in challenges. I store the time each time the users enter a new challenge. The query was working well in the begging but after that it stops showing new users and only old users appears in it.
this is the query code :
usersReference.orderByChild("lastChallengeDate")
.limitToLast(15)
.addListenerForSingleValueEvent(new ValueEventListener()
and this is the database structre of the user child :
When I opened the log I found this warn although I am using index on in my rules
W/PersistentConnection: pc_0 - Using an unspecified index. Consider adding '".indexOn": "lastChallengeDate"' at users to your security and Firebase Database rules for better performance
If you perform a query on a location, Firebase sorts the children under that location on the property you specify. There is no value in lastChallengeDate directly under each child of users. Instead the property is under lastChallengeDate/time, so you should order on that
usersReference.orderByChild("lastChallengeDate/time")
.limitToLast(15)
.addListenerForSingleValueEvent(new ValueEventListener()
You also need to define an index on users (or whatever the name is of the node you query):
{
"rules": {
"users": {
".indexOn": "lastChallengeDate/time"
}
}
}
Be sure to also study:
the documentation on queries, which includes an example of querying such a nested property
the documentation on defining indexes
some of the many questions with the same error message
I have a node that I refresh every three days with some key-value pairs in my firebase realtime database. I want my app to get the new values only when I make changes in this node (so about every three days). I currently use this code to test :
mFirebaseDatabase.getReference().child("test").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long tsLong = System.currentTimeMillis();
Log.d("thatsdatasnapshot", "thatsdatasnapshot = " + tsLong.toString());
Log.d("thatsdatasnapshot", "thatsdatasnapshot = " + dataSnapshot.toString());
}
My issue is that my logs in this listener print very often even I don't change anything in my node, for example everytime I start the app. So I guess that all the values of my node are downloaded "very often", not only when I make change in my database. Am I wrong ? How to download the values of my node only when there is a change ? I thought it was what addValueEventListener() should do but I have a doubt when I see my logs printed so often.
Thank you,
Alex
The method addValueEventListener is only triggered when values in the realtime db change during your current run of the app, such as for every mRef.push() or mRef.child("someChild").setValue() method call in your app.
I had almost the same kind of problem with firebase realtime database and in the end, i resorted to creating an AsyncTask to update what you have to update during your app's runtime.
What you have to do is create an AsyncTask and make a REST call to your Firebase Database, and use it to update.