I followed the documentation, but no matter what, I cannot figure out how to return all the objects from a single node. For example, I want to return a list of all company objects from the companies node. Once I have that list, I want to parse them all into JSON objects. This is my first time with a NoSQL database so I'm sure that I'm missing something small.
Currently I have:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference("12265");
companiesRef.child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But it just returns null for the value: DataSnapshot { key = companies, value = null }.
Here's my database:
You create your reference like this:
FirebaseDatabase.getInstance().getReference("12265");
This means that Firebase looks at the root of the database and returns the child 12265 from under there. It does not automatically search the tree for a node with a matching name.
So you'll need to specify the entire path:
FirebaseDatabase.getInstance().getReference("android/users/12265");
Don't add any parameters to your getReference() (let it go to the root of database) and then set the addListenerForSingleValueEvent. And you have not used getvalue() on you datasnapshot as well. Try this code:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference();
// this is the patch that I see from the image that you have attached.
companiesRef.child("telenotes").child("android").child("user").child("12265").child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Related
I am trying to retrieve a list that is on a child that starts with something. Below is a sample of data in my Firebase realtime database:
In the image, I want to retrieve all data that starts with the keyword "jsonmat".
I am using thee code below but it always return null:
DatabaseReference db = FirebaseDatabase.getInstance().getReference()
.child("Events");
db.startAt("jsonmat").addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i("events", dataSnapshot.toString());
for (DataSnapshot data : dataSnapshot.getChildren()) {
// here the user will have the specified email only
}
}
#Override
public void onCancelled(DatabaseError databaseError){
Log.i("MyApp", "getUser:onCancelled", databaseError.toException());
}
});
What you're trying to do isn't possible. You can't order/filter of a nested key, only on direct child keys (-M...) and on nested values (active: true).
Typically you'll want to create a new top-level node, where you store the keys you're searching for, and then the push keys for each matching nested node:
"category_things": {
"jsonmat_jsonmat": {
"-M62....uYgB": true,
"-M62....2-eO": true
}
}
Also see:
Firebase Query Double Nested
My original, but wrong answer is below...
If you use startAt without specifying an orderBy... clause, the data will be ordered by priority. This priority is a left-over from before Firebase supported ordering on specific properties, so mostly it means that you must call an orderBy... method before filtering.
So:
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("Events");
db.orderByKey().startAt("jsonmat").addListenerForSingleValueEvent(new ValueEventListener() {
...
What you can do for your case, is to loop 2 times over the children of the node Events:
//the reference to the node Events
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("Events");
db.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//loop 1
for (DataSnapshot data : dataSnapshot.getChildren()) {
//loop2
for (DataSnapshot dataTwo : data.getChildren()) {
//get the key
String key = dataTwo.getKey();
if(key.startsWith("jsonmat")){
//we got a matching key so extract the data and maybe put them in a list
boolean active = dataTwo.child("active").getValue(Boolean.class);
int bet = dataTwo.child("bet").getValue(Integer.class);
String challenger = dataTwo.child("challenger").getValue(String.class);
String competitor = dataTwo.child("competitor").getValue(String.class);
String game = dataTwo.child("game").getValue(String.class);
............
............
............
}else{
//we didn't get a match
}
}//end loop2
}//end loop1
}
#Override
public void onCancelled(DatabaseError databaseError){
Log.i("MyApp", "getUser:onCancelled", databaseError.toException());
}
});
Explanation -
DatabaseReference Ref;
//intialize Ref variable
Ref = FirebaseDatabase.getInstance().getReference(); //root reference
after this, adding the valueEventListener to Ref
Ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("abcd")) {
//abcd child is present
}else {
//abcd child is not present
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Now Specifically my question is which algorithm does the firebase using behind the dataSnapshot.hasChild("abcd") ?
In Firebase-database if my root reference contains a huge number of childs then this is an efficient method to use or not?
A DataSnapshot is an efficiently-generated immutable copy of the data at a Firebase Database location. It can't be modified and will never change.
The hasChild(key) can be considered a convenience method for child(key).exists(). As keys are always unique, there is no need to iterate the entire snapshot to locate a specific key, and therefore performance should be something similar to a HashMap at O(1).
If you do have a huge amount of data though, it is often unnecessary to download everything at once, so it's recommended to filter or restrict your query, or select a deeper node and then only obtain a subset of data at a time.
For example, you could listen lower in the tree, for the abcd node directly, and then use the exists() method instead to check for the existence of a child node:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.child("abcd").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
DataSnapshot child = dataSnapshot.child("efgh");
if (child.exists()) {
//efgh child is present
} else {
//efgh child is not present
}
}
#Override
public void onCancelled(DatabaseError databaseError) { }
});
I am storing user details 'firstname' and 'lastname' in UserNode. But when i want to retrieve that details then no data is being retrieved. I tried almost all solutions on the internet but nothing solved my problem. Here is my code for retrieving data of the current user:
FirebaseUser userr = FirebaseAuth.getInstance().getCurrentUser();
if (userr != null) {
String name = userr.getDisplayName();
Log.e("value", name);
}
but it says "println needs a message"
I also tried with this but nothing happened:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String acctname = (String)dataSnapshot.child("firstname").getValue();
Log.e("name", acctname);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
]1
Please help me I am stuck with it
You're reading a collection of user with a ValueEventListener. As the [Firebase documentation for reading lists with a value event](Listen for value events) explains:
While using a ChildEventListener is the recommended way to read lists of data, there are situations where attaching a ValueEventListener to a list reference is useful.
Attaching a ValueEventListener to a list of data will return the entire list of data as a single DataSnapshot, which you can then loop over to access individual children.
Even when there is only a single [child node], the snapshot is still a list; it just contains a single item. To access the item, you need to loop over the result.
So in your code:
DatabaseReference DataRef;
DataRef = FirebaseDatabase.getInstance().getReference().child("UserNode");
DataRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String acctname = (String)childSnapshot.child("firstname").getValue();
Log.i("name", acctname);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
Using FirebaseUser:
FirebaseUser implements UserInfo and in UserInfo's getDisplayName() documentation says
Returns the user's display name, if available.
So, it is possible that FirebaseUser.getDisplayName() return null when display name is not set. In that case Log.e() receives null as message and therefore prints println needs a message
Using your own structure:
Instead of using type conversion use getValue(Class<T>) like so:
String acctname = dataSnapshot.child("firstname").getValue(String.class);
Please, read how to retrieve data from firebase. I think you have a problem because you don't have Class Model.
Your steps:
Create model UserModel with firstname and lastname field
Use listener (example from docs):
// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Post post = dataSnapshot.getValue(Post.class);
System.out.println(post);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
See other answers: How to retrieve data from one single userID Firebase Android and retrieving data from firebase android
I have this data in Firebase Database:
Negocios:
-KjfCu56lFZCybYldBZy
lugarReference: "Restaurante"
numeroMesas:39
password:"pass123"
user:"user123"
user_id:"usr_1"
I have two applications connected to one project in Firebase, one of them upload data of restaurants reservation, and the other one displays reservations in a RecyclerView.
In the first application, once I do a reservation, it must minus one to numeroMesas value, the other application should display any changes to this key.
In the reservation application, I have this piece of code that I did base in this question:
Update specific keys using Firebase for Android
It supposes to modify the value of numeroMesas, but it does not:
mReference.child("Negocios").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot : dataSnapshot.getChildren()){
Lugar lugar = postSnapshot.getValue(Lugar.class);
if(nombre_lugar.equals(lugar.getUser_id())){
DatabaseReference numMesasReference = mReference.child(dataSnapshot.getKey()).child("numeroMesas");
numMesasReference.setValue(lugar.getNumeroMesas() - 1);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
What it does is the next thing:
Negocios:
-KjfCu56lFZCybYldBZy
lugarReference: "Restaurante"
numeroMesas:39
password:"pass123"
user:"user123"
user_id:"usr_1"
-Negocios
-KjfCu56lFZCybYldBZy
numeroMesas:39
How can be fixed?
I need to minus one once I do a reservation...
Greetings!
Using postSnapshot.getRef() you obtain a reference to the source location for this snapshot. So what's next is to add a child to that reference, that reference will be "numeroMesas" that is the key you want to modify.
As easy as that, the code will be like this.
mReference.child("Negocios").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot : dataSnapshot.getChildren()){
Lugar lugar = postSnapshot.getValue(Lugar.class);
if(nombre_lugar.equals(lugar.getUser_id())){
DatabaseReference numMesasReference = postSnapshot.getRef().child("numeroMesas");
numMesasReference.setValue(lugar.getNumeroMesas() - 1);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
P.S: If you want to minus one just once by reservation, addValueEventListener() won't work, it will minus multiple time as a loop. Use addListenerForSingleValueEvent() instead addValueEventListener().
As the name says, this listener fits for single changes in the data at any location.
I guess the problem is with dataSnapshot.getKey() in this line
DatabaseReference numMesasReference = mReference.child(dataSnapshot.getKey()).child("numeroMesas");
Here you getting the key for the whole list of Negocios, not for the specific child replace it with `
postSnapshot.getKey()
The problem is that your DatabaseReference that you are using is wrong. You are missing a child. So in order to solve this problem, please use the following code:
mReference.child("Negocios").child(negociosId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int numeroMesas = (int) dataSnapshot.child("numeroMesas").getValue();
if(nombre_lugar.equals(lugar.getUser_id())){
mReference.child("Negocios").child(negociosId).child("numeroMesas").setValue(numeroMesas - 1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
In which negociosId is the unique id generated by the push() method.
Hope it helps.
I'm new to firebase and android. But If the above solutions doesn't work please do the following. I think the problem is that you didn't convert the value of numeroMesas to string. Sorry if there's anything wrong.
Hope it helps.
mReference.child("Negocios").child(negociosId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(nombre_lugar.equals(lugar.getUser_id())){
mReference.child("Negocios").child(negociosId).child("numeroMesas").setValue((Integer.parseInt(dataSnapshot.child("numeroMesas").getValue().toString())) - 1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
I'm making a post app with Firebase Realtime Database.
The app needs a bookmark function, but I don't know how to load the bookmarked (selected) post.
Database structure:
Code:
databaseReference = databaseReference.child("post").child(getLen()).child("all-posts").child("-KYbMBatKdoWYw45-2pp").child("bookmarkUsers").orderByChild(myUserId).equalTo(myUserId);
but this code is not working. Why doesn't it work? I think that it only returns bookmarkUsers child node.
Do I have to make another node only for bookmark?
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
Thanks!
DatabaseStorage Posts=FirebaseDatabase.getInstance().getReference().child("posts");
Posts.child("0").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot DS: dataSnapshot)
{
//Get all other Values Except bookmarkusers and store them
String POST_NAME = dataSnapshot.getKey();
Posts.child("0").child(POST_NAME)addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshotf) {
for(DataSnapshot BOOK: dataSnapshotf)
{
//Collect all BookMarks and store them
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Do I have to make another node only for bookmark?
Yes, you do. To get more information, read about structuring you data in firebase here.
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
You will need to keep the bookmarkCount and starCount inside the post node itself.