This is my JSON Structure:
{
"users" : {
"userKey1" : {
"deviceToken" : "deviceTokenID",
"displayName" : "Name here",
"dob" : "28/6/2017",
"email" : "efg#wxy.com",
"gender" : "M"
},
"userKey2" : {
"deviceToken" : "deviceTokenID",
"displayName" : "Name here",
"dob" : "28/1/2017",
"email" : "abc#xyz.com",
"gender" : "M",
}
}
}
In my android Firebase file, I type this:
Query findUser = mDatabase.child("users").orderByChild("email").equalTo("abc#xyz.com");
findUser.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Log.i("findUser","Snapshot: " + dataSnapshot.toString());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I get the following log:
06-28 22:06:50.190 30962-30962/in.sample.project I/findUser: Snapshot: DataSnapshot { key = users, value = null }
I do not know why I am getting null when cleary I have a child who's email node matches "abc#xyz.com".
You need a foreach loop to get the user in your findUser query because your query contains a collection.
Query findUser = mDatabase.child("users").orderByChild("email").equalTo("abc#xyz.com");
put this part in your eventlistener
....
public Iterable<DataSnapshot> getChildren (){
for (DataSnapshot child : parent.getChildren()) {
....
}
}
Needed to add security rules.
rules: {
"users" : {
".indexOn": "email",
}
}
I guess, that did the trick. Hope it helps someone. :)
Related
I created a helper class including the functions and processes I would like to perform over my data in FirebaseDatabase.
The following function was meant to get all Posts in posts Node in fireabseDataBase:
public static Jobs getAllJobs() {
Posts posts= new Posts();
postsDBRef= FirebaseDatabase.getInstance().getReference("posts").getRef();
postsDBRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot jobSnapshot: dataSnapshot.getChildren()) {
// TODO: handle the post
String key = jobSnapshot.getKey();
//here
Post post= jobSnapshot.child(key).getValue(Post.class);
// and here
posts.add(post);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i(getClass().getName().toString(), ": " + databaseError.getMessage());
}
});
return posts;
}
in the onDataChange function I am trying to loop over the data and retrieve it, although while logging I do get data but the post object keeps giving Null
Here's How the data look like in firebase DataBase
{
"posts" : {
"-Kr9-ii-ArpC3fLuuGnb" : {
"address" : "sfhhfg",
"applied" : false,
"currency" : "le",
"description" : "ehdhyf",
"latitude" : 0,
"longitude" : 0,
"noOfWorkers" : 2,
"rating" : 0,
"reported" : false,
"salary" : "1250",
"title" : "rgchu",
"userId" : 0
},
"-Kr94BDkdEZrmxmjxv_Z" : {
/../
},
"-Kr9Dz3S0BQEYv4VO2l3" : {
/../
},
"-Kr9XqDPUvCRcv0lwFy_" : {
/../
}
}
}
and here’s what am getting from the Debugger in a single loop
DataSnapshot { key = -Kr9-ii-ArpC3fLuuGnb, value = {address=sfhhfg,
rating=0, title=rgchu, reported=false, description=ehdhyf, userId=0,
longitude=0, noOfWorkers=2, latitude=0, currency=le, applied=false,
salary=1250} }
Any idea what am I doing wrong?
After several trials
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Job job = snapshot.getValue(Job.class);
System.out.println(job.getTitle());
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i(getClass().getName().toString(), ": " + databaseError.getMessage());
}
});
Using .addChildEventListener was the only Solution for my issue, Still investigation the reason.
i have edited your code and it should work fine now, i have used the same code snippets in several projects before. make sure your pojo matches the json data, you can use this tool to make it easier for yourself.
and the most important thing , Don't use Firebase as functions that return values - it goes against it's asynchronous nature.make Firebase perform it's task and then within the closure (block) go to the next step.
P.S: before using ValueEventListener or ChildEventListener read the difference between them from here.
public void getAllJobs() {
Posts posts= new Posts();
postsDBRef= FirebaseDatabase.getInstance();
postsDBRef.child("posts").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot jobSnapshot: dataSnapshot.getChildren()) {
Post post= jobSnapshot.getValue(Post.class);
posts.add(post);
}
// go to next step from here e.g handlePosts(posts);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.i(getClass().getName().toString(), ": " + databaseError.getMessage());
}
});
}
This is my Firebase structure:
"Braccianti" : {
"-KehahFy7z2IrUdchwxk" : {
"Associazione" : "-KehahFy7z4ngUdchwxk",
"Cellulare" : "3402659753",
"Cognome" : "Prova",
"DataDiNascita" : "12/04/1985",
"Nome" : "Bracciante"
},
"ashaosdfao" : {
"Associazione" : "gsdfskjdfsdf",
"Cellulare" : 234235246,
"Cognome" : "Example",
"DataDiNascita" : "10/12/2000",
"Nome" : "exam"
}
"dfsdfsdfsdf" : {
"Associazione" : "ewsvbdtgsdgf",
"Cellulare" : 23523975553,
"Cognome" : "Ex",
"DataDiNascita" : "17/01/1994",
"Nome" : "ghjghj"
}
}
I'd like to get "dfsdfsdfsdf" and "-KehahFy7z2IrUdchwxk" with a single query, so i thought about doing like this:
Query QueryAssociazioni = FirebaseDatabase.getInstance().getReference("Aziende/"+main.getNomeAzienda()+"/Associazioni");
QueryAssociazioni = QueryAssociazioni.equalTo("dfsdfsdfsdf").equalTo("-KehahFy7z2IrUdchwxk");
But it doesn't work.
How can i solve my problem?
Firebase doesn't allow multiple queries, but you can always add a ChildEventListener and check if the child's value :
QueryAssociazioni.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String child = dataSnapshot.getValue().toString();
if(child.equals("dfsdfsdfsdf") || child.equals(("-KehahFy7z2IrUdchwxk"))){
//Do something with the value
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
QueryAssociazioni.child("Braccianti")
.orderByChild("Associazione") //key name
.equalTo("Associazione") //value
Try this way...
Thanks.
I want to retrieve data for a given user ID, which I am storing as a value in the database under each user. My database structure looks like below:
user: {
UserID: {
uniqueId: {
Name: ""
Email: ""
userId: ""
}
UserID: {
uniqueId: {
Name: ""
Email: ""
userId: ""
}
}
I tried this but it doesn't seem to work as it doesn't display anything on the app:
FirebaseUser user = mAuth.getCurrentUser();
df.child("UsersTable").orderByChild("userid").equalTo(user.getUid())).addChildEventListener
even when I try to give a specific value like below, it still does not read from firebase:
------------- Updated:
I want to get all data from userID. so for example, I want to retrieve all information from fmXWU324VHdDb8v6h7gvNjRojnu33, which will be name, email and userid.
UserTable
{
"fmXWU324VHdDb8v6h7gvNjRojnu33" : {
"-KbJtw467nl6p253HZ537" : {
"Name" : "name1",
"Email" : "something1#something.com",
"userid" : "fmXWU324VHdDb8v6h7gvNjRojnu33"
}
},
"pJtC45fW0MMi352UiPWnWdIS7h88" : {
"-Kb012ls9iMnzEL723o9I" : {
"Name" : "name2",
"Email" : "something2#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
},
"-Kb0aq0q25FJq38256SrC" : {
"Name" : "name3",
"Email" : "something3#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
},
"-Kb0atopfK64F6jy124Qi1u" : {
"Name" : "name3",
"Email" : "something1#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
}
}
Update 2:
DatabaseReference df= FirebaseDatabase.getInstance()
.getReference("user").child(getCurrentUser().getUid());
df.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
get(dataSnapshot);
}
....
...
Update 3:
I assume based on what I am looking for (getting all data under defined userId) the query should look something like this:
df.child("UserTable").child(user.getUid())).addChildEventListener(new ChildEventListener()
However, this is throwing this error:
Can't convert object of type java.lang.String to type com.android.example.UserTable
Try Using addChildEventListener and Query like following..
mReference.child("user").orderByChild("userId").equalTo(user.getUid()).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//deal with data object
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
OR use addValueEventListener
mReference.child("user").orderByChild("userId").equalTo(user.getUid()).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//deal with data object
}
#Override
public void onCancelled(DatabaseError databaseError) {
//toastMsg(databaseError.getMessage());
Log.e(TAG, "onCancelled: " + databaseError.getMessage());
}
});
Use something like the below code which i am using in my application and it works -
public static void storagesSetup(final Context context){
if(!hasSignedInUser()) {
**your business logic here**
return;
}
// Write a message to the database
final DatabaseReference databaseRef = FirebaseDatabase.getInstance()
.getReference("cart").child(getCurrentUser().getUid());
// Read from the database
databaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
**put your business logic here**
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
A Firebase Database query inspects the child nodes directly under the location that you execute it on. If you want to order on a child property of those nodes (i.e. use orderByChild()), that property must exist at a fixed path under each child nodes.
In your case, you have two nested dynamic children, which means you:
can query a known user for their results ordered by score
can't query across all users for their results ordered by score
If you want to allow the latter query, you'll need to change your data model to allow it. For example, by keeping a list of all results across all players:
ResultsTable:{
"-KbJtw467nl6p253HZ537" : {
"Name" : "name1",
"Email" : "something1#something.com",
"userid" : "fmXWU324VHdDb8v6h7gvNjRojnu33"
},
"-Kb012ls9iMnzEL723o9I" : {
"Name" : "name2",
"Email" : "something2#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
},
"-Kb0aq0q25FJq38256SrC" : {
"Name" : "name3",
"Email" : "something3#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
},
"-Kb0atopfK64F6jy124Qi1u" : {
"Name" : "name3",
"Email" : "something1#something.com",
"userid" : "pJtC45fW0MMi352UiPWnWdIS7h88"
}
}
Please get a idea from below code.
Order objects:
DatabaseReference mDatabaseReference = FirebaseDatabase.getInstance()
.getReference();
DatabaseReference node = mDatabaseReference.child("order")
node.orderByChild("timestamp").equalTo("-KZFQLVAv_kARdfnNnib")
.addValueEventListener(mValueEventListener);
private ValueEventListener mValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
Log.i(TAG, "onDataChange: " + snapshot.getValue());
// Your code
}
#Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "onCancelled: " + error.getMessage());
}
};
This return the first order object. Hope you get the point Thanks! :)
"sicknessEntries" : [ null, {
"daysSick" : 1,
"sickness" : "Flu",
"type" : "Viral",
"userId" : "K9lPzGCb1AUdNqNywurwNueunv42"
},
-K9lP-zGCb1AUdNqNywurwN {
"daysSick" : 2,
"sickness" : "Pneumonia",
"type" : "Bacterial",
"userId" : "abcd"
},
-NywurwNueunv42 {
"daysSick" : 1,
"severity" : "Medium",
"sickness" : "Shingles",
"type" : "Viral",
"userId" : "user123"
},
{
"daysSick" : 1,
"severity" : "Medium",
"sickness" : "Flu",
"type" : "Viral",
"userId" : "K9lPzGCb1AUdNqNywurwNueunv42"
} ]
For the above json it shows different type of child i have to retrieve only value of the key "sickness" whether it is in the direct child or in the sub child?
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot friendSnapshot: dataSnapshot.getChildren()) {
System.out.println(friendSnapshot.child("sickness").getValue());
}
}
public void onCancelled(DatabaseError databaseError) {
}
});
If i use the above code it can get only the main child values for the key "sickness" (i.e. it returns the both Flu, Flu only not the others). But i have to get all the sub child values too which have the same key. How to retrieve it?
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference refUsers = database.getReference("/childname");
refUsers.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
try {
Iterable<DataSnapshot> children = dataSnapshot.child("sicknessEntries").getChildren();
List<SickModel> sickList = new ArrayList<>();
for (DataSnapshot child : children) {
SickModel sickmodel = child.getValue(SickModel.class);
sickList.add(sickmodel);
}
Try the above code snippet,for retrieving array of sickmodel.
Where sickmodel has daysSick ,sickness,type,userId
This is my data:
{
"users" : {
"00c49c66-7ac8-9a48-7c4541d8bac6" : {
"email" : "d#gmail.com",
"gender" : "m",
"name" : "deepak",
"user_id" : "00c49c66-7ac8-9a48-7c4541d8bac6"
},
"1cb9c1de-1fcf-a2cc-bf78c84e03c8" : {
"email" : "e#gmail.com",
"gender" : "f",
"name" : "ekta",
"user_id" : "1cb9c1de-1fcf-a2cc-bf78c84e03c8"
},
"38211c3f-6c48-8987-0c698b9b9b52" : {
"email" : "c#gmail.com",
"gender" : "m",
"name" : "chirag",
"user_id" : "38211c3f-6c48-8987-0c698b9b9b52"
},
"a536cf1f-419f-9658-cfb5f5a8ec78" : {
"email" : "a#gmail.com",
"gender" : "m",
"name" : "aniket",
"user_id" : "a536cf1f-419f-9658-cfb5f5a8ec78"
},
"c80d828d-48d7-a79a-9cc558cd1960" : {
"email" : "b#gmail.com",
"gender" : "f",
"name" : "bhakti",
"user_id" : "c80d828d-48d7-a79a-9cc558cd1960"
}
}
}
Now I want to get 'name' and 'id' where 'gender' is "m"
Please can anyone tell me how to fire a query like this from Android client to firebase.
I tried tutorials provided by firebase and few other links but didn't got through.
Most of solutions are in Javascript I need it for Android in firebase's java api.
I tried this
public class ActivityHome extends Activity {
String strLoggedInUserID;
TextView tvData;
Firebase fbRef = new Firebase("https://myurl.com/users");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
tvData = (TextView) findViewById(R.id.tvData);
Query queryRef = fbRef.orderByChild("gender").equalTo("m");
Bundle extras = getIntent().getExtras();
strLoggedInUserID = extras.getString("userID");
fbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
queryRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//long longChildCount = dataSnapshot.getChildrenCount();
// tvData.setText(dataSnapshot).toString();
tvData.setText(s);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
//tvData.setText(s);
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
}
Your querying code looks correct, but you're not printing the user.
Since you're adding a ChildEventListener, it will be called for each child:
queryRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//long longChildCount = dataSnapshot.getChildrenCount();
// tvData.setText(dataSnapshot).toString();
tvData.setText(s);
}
The dataSnapshot parameter contains information about a single user. To print their key, name and email:
queryRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
System.out.println(dataSnapshot.key());
System.out.println(dataSnapshot.child("name").getValue());
System.out.println(dataSnapshot.child("email").getValue());
}
Alternatively, you can listen to all children at once with a ValueEventListener.
private static class User {
String email;
String gender;
String name;
#JsonProperty("user_id")
String userId;
public String getEmail() { return email; }
public String getGender() { return gender; }
public String getName() { return name; }
public String getUserId() { return userId; }
}
queryRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
User user = child.getValue(User.class);
System.out.println(user.getEmail());
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
In this last snippet I also use a User class for getting the data from DataSnapshot. As your application grows, this will be more convenient than constantly calling DataSnapshot.child().
This is covered in the section on reading data in the Firebase documentation.