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) { }
});
Related
how email's value change from "app-user/users"?
Firebase state :
this isn't web language, i use javacode and xml of androidstudio.
i'm tryed under code.
databaseReference.child(app-user).child(user).orderByChild("email").equalTo("user4~~")
I don't know what to do next.
To get all users whose email address starts with user4:
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference().child("app-users/users");
Query usersQuery = usersRef.orderByChild("email").startAt("user4").endAt("user4\uF7FF");
usersQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.getKey()+": "+userSnapshot.getChild("displayName").getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
To understand the usersRef.orderByChild("email").startAt("user4").endAt("user4\uF7FF") query, read it as:
Take all child nodes of usersRef and order them by their email property.
Then find the first child node that starts with user4.
Then return each child node, until you find a child that starts with .endAt("user4\uF7FF") (or further).
In this the \uF7FF is no magic code, but just the last known Unicode character. So by combining .startAt("user4").endAt("user4\uF7FF"), you're building a startsWith operator.
I am getting an error while retriving data from Firebase in Android app.
Error
My code:
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
"path" - child's name.
And my
Your code read all data from the root of your data.
So what you get in the dataSnapshot passed to onDataChange is:
{
"uzmtn": "data"
}
Then you call dataSnapshot.getValue(String.class) on it, which isn't possible: the value in the snapshot isn't a string.
There are two simple options to fix it:
read data lower in the tree
get the correct child from the existing snapshot
I'll start with the second, since it stays closest to your code.
get the correct child from the existing snapshot
Since you're already getting the entire JSON in dataSnapshot, you can use the methods of the DataSnapshot class to find the value you want.
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.child("uzmtn").getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
While this works, you're reading slightly more data than is needed. It isn't too bad here, but as a general case: it is best to only read the precise data you need.
To do that, we can...
read data lower in the tree
Instead of listening for the root of the database, you can attach a listener straight to the uzmtn node:
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("uzmtn");
DatabaseReference ref = databaseReference.child(path);
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
ClipboardManager clipboard = (ClipboardManager) getApplicationContext().getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(value);
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
If you do that, the dataSnapshot will contain precisely the string you are looking for:
"data"
And with this in the snapshot, the call to dataSnapshot.getValue(String.class) will work.
You are returning a hashmap type because you didn't specify what child you want to return . Imagine your data structure like a tree in firebase database , each node has its own value .
What you want to return it's the child node from a tree , but instead , you return the node itself , which will return the node itself and the whole child node .
Simple solution is
dataSnapshot.child('emtz').getValue() .....
I'm trying to display the "loc" of a part if its part number I given.
Here is what the data structure looks like:
{
"parts":{
"14521845": { "name":"TOOL EC160B/EC180B/EC210B/EC240", "loc":"EXC1", "sloc":"B3EGU01C03"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"PS01", "sloc":"85-06-013"},
"12829050": { "name":"SWITCH; IGNITION SWITCH", "loc":"COM1", "sloc":"B3RGK03D06"},
"20044893": { "name":"PARTS CATALOG_ENG_SPA_FRE_GER_KOR_EC210D", "loc":"EXC1", "sloc":"B3EGT01B02"}
}
}
Activity Code:
FirebaseDatabase firebaseDatabase=FirebaseDatabase.getInstance();
DatabaseReference databaseReference =firebaseDatabase.getReference("parts/"+curP);
databaseReference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data=dataSnapshot.getValue(Products.class);
Log.i("",String.valueOf(data.getLoc()));
}
getLoc is the getter function for the Product class, and it returns the corresponding "loc" for the given curP. curP denoted the child values in parts.
The logic seems right to me, but I am not getting an output. Where am I going wrong here?
try this
getReference("parts").child(curP).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Products data = dataSnapshot.getValue(Products.class);
Log.i("", String.valueOf(data.getLoc()));
}
});
The problem is that what you are getting in onChildAdded() is not a whole Product object as you expect it to be.
In your database reference you are targeting a specific Product ("parts/"+curP) but using a ChildEventListener. The children of a specific product node are name, loc and sloc, so the onChildAdded() will trigger several times, giving you each of these properties as a dataSnapshot separately.
The two patterns you might use to get whole Product objects are either:
add a ChildEventListener directly to the "parts" node and you will get each of the Products as a child of that node, or;
if you are adding a listener directly to the node of a particular product, use a ValueEventListener, to get the whole of that nodes entry as one dataSnapshot.
You can try to use ValueEventListener. If you want read data once so use the addListenerForSingleValueEvent method, something like this:
private void getFirebaseLocValue(int curP) {
FirebaseDatabase firebase = FirebaseDatabase.getInstance();
DatabaseReference mDatabase = firebase.getReference("parts");
mDatabase.child(Integer.toString(curP))
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChildren()) {
Products data = dataSnapshot.getValue(Products.class);
Log.e("TAG", data.getLoc());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Or you can use addValueEventListener and will get data with any changes. I really don't think that ChildEventListener is a good idea to retrieve data from Firebase.
I want to retrieve the messages data under a specific key. But I don't how to get the key. Please help, I'm new to firebase.
In my case right now, I want to get the key encircled below.
I have tried this code below but this returns "chat-mates" not the key.
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference().child("chat").child("single-chat").child("converstation").child("chat-mates");
ref.orderByChild("receiverName").equalTo("Liza Soberano").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()){
String key = child.getKey();
Log.e("Key", key);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I have tried this code below but this returns "chat-mates" not the key.
You must be using DataSnapshot method to access the JSON tree.
The DataSnapshot element has a method called getKey(). That returns the key of an object.
Official Doc: DataSnapShot getKey() method
Example Code:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot objSnapshot: snapshot.getChildren()) {
Object obj = objSnapshot.getKey();
}
}
#Override
public void onCancelled(DatabaseError firebaseError) {
Log.e("Read failed", firebaseError.getMessage());
}
});
In your case, first get to the child node "conversation" and then apply the above method getKey().
You're building your path wrong and likely end up iterating a different part of the tree, one level above child-mates. In that case it would be correct that child-mates is a child key.
The problem is in the last child() call when you create the ref:
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference()
.child("chat")
.child("single-chat")
.child("converstation")
.child("chat-mates");
There is no child chat-mates under converstation, so this ref won't be correct.
You probably want to do this:
final DatabaseReference ref =FirebaseDatabase.getInstance().getReference()
.child("chat")
.child("single-chat")
.child("converstation");
ref.orderByChild("chat-mates/receiverName")
.equalTo("Liza Soberano")
.addListenerForSingleValueEvent(new ValueEventListener() {
This will filter on the chat-mates/receiverName child of each chat.
Note that you're going against one of Firebase's recommendations with this data structure. Firebase recommends against nesting data types in the way you do here.
A more denormalized data model would be:
chat-mates
$chatRoomId
receiverName
senderName
chat-messages
$chatRoomId
$messageId
This way you can get the mates/participants in a chat, without accessing (or even needing to have access to) the messages themselves.
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) {
}
});