How to Query Data in Firebase by Specific Child Value? - android

I'm starting with firebase and I have a problem with data query. I have this firebase database:
"Conversations" : {
"-L9LJQiFKqGlNKKFEyvd" : {
"-L9LJQiHrp1rU1pblNG_" : {
"messageText" : "Hi there",
"postTime" : 1522940321427,
"senderId" : "GSJMlFA3pYMjYCfY6BA0AEyva9u2",
"senderNickname" : "q"
},
"-L9LZ0O2rXHe-eh2iRgB" : {
"messageText" : "f",
"postTime" : 1522944447238,
"senderId" : "GSJMlFA3pYMjYCfY6BA0AEyva9u2",
"senderNickname" : "q"
},
"-L9LZ7uF9TPb4VZ-wJEO" : {
"messageText" : "vvvv",
"postTime" : 1522944478035,
"senderId" : "GSJMlFA3pYMjYCfY6BA0AEyva9u2",
"senderNickname" : "q"
}
}
},
I would like to show get reference to those push() object which "postTime" value is higher than some specific value like for example: 1522944447230.
I've tried with:
mConversationId = "-L9LJQiFKqGlNKKFEyvd"
mLeaveTime = 1522944447230;
mUserConversationsReference = mFirebaseDatabase.getReference().child("Conversations");
mUserConversationsMessagesReference = mUserConversationsReference.child(mConversationId);
mLastMessageQuery = mUserConversationsMessagesReference.orderByChild("postTime").orderByValue().startAt(mLeaveTime);
but then I get:
java.lang.IllegalArgumentException: You can't combine multiple orderBy
calls!
So there must be probably another way to solve this issue. I would be grateful for any advice.`

To solve this, please use the floowing lines of code:
String mConversationId = "-L9LJQiFKqGlNKKFEyvd"
long mLeaveTime = 1522944447230;
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mConversationIdRef = rootRef.child("Conversations").child(mConversationId);
Query query = mConversationIdRef.orderByChild("postTime").startAt(mLeaveTime);
.orderByValue() has nothing to do you in this query. And note, Firebase does not allow you to use multiple orderBy calls. So to solve this, ony one is enough.

Related

Filtering by grandchild without knowing child's key in Firebase

I'm a newbie working on an Android project using Firebase v3.
I have set up a data structure that relates stores to brands as follows:
stores -> [brandId] -> [storeId] -> store object
"stores" : {
"1z05cQF7FnWkCTe2KC9eqCHi6Ji2" : {
"hSlKozrMq2aNGQqWDZ7eU2UzNtr1" : {
"brid" : "1z05cQF7FnWkCTe2KC9eqCHi6Ji2",
"email" : "di#cof.ci",
"uid" : "hSlKozrMq2aNGQqWDZ7eU2UzNtr1"
}
},
"LqZ81PF7bKXPtoASWUWMQKFYMK62" : {
"-Kidnq4rlssa5d1Ic8gv" : {
"brid" : "LqZ81PF7bKXPtoASWUWMQKFYMK62",
"email" : "test#test.test",
"uid" : "-Kidnq4rlssa5d1Ic8gv"
}
},
}
I would like without knowing the brandId to get the store object.
Is that possible?
I tried using orderByChild and orderByKey but nothing seems to work, either everything is returned or null.
e.g.
var tellerRef = firebase.database().ref('/stores/');
tellerRef.orderByChild(uid).once('value').then((snapshot) => console.log(snapshot.val()));
where uid = "hSlKozrMq2aNGQqWDZ7eU2UzNtr1" returns everything!

Query to retrieve specific data from Firebase

I am creating an android app and I am stuck at a problem. In order to explain the problem, I would like to show my database structure
{
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contacts" : {
"Contact1" : value (Contact number)
"Contact2" : value
"Contact3" : value
},
"name" : "Sagar Khan",
"phone" : 7276273667
},
"OLm7VWsMcGQpterECyhJ8YTSPna2" : {
"Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Sameer",
"phone" : 8412914728
},
"TXanCkqtB5PdEogtv8Dzw8y1ngw1" : {
""Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Harish",
"phone" : 7020743544
},
"qnDVoc72nXa8XvOH1L39VvqFzKL2" : {
"Contacts" : {
"Contact1" : value
"Contact2" : value
"Contact3" : value
},
"name" : "Harish Shinde"
"phone": 8149870822
}
}
This is very short structure the actual one is to big
Now what I want to do is I want to fetch only those users whose contact number is present in current user node and display those users in a Android list.
For example:
User 1 with id EXlzg1COUbOhQjwPCGbS1NRdp5H3 is having 3 contacts
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contacts" : {
"Sameer" : 8412914728 (Contact number)
"Contact2" : value
"Contact3" : value
},
"name" : "Sagar Khan",
"phone" : 7276273667
},
Now when I will fetch the list of users from my database and show it in my Android app list, I want only those users to be added whose contact number is present in User 1 contacts.
My problem is that I literally don't know how to do this as I am new to Android development and Firebase. I am clear with the read and write basics of Firebase, but such operations, I have no idea how to do it.
I have searched a lot, but cannot find any solutions or examples. A detailed description will be very good for me. ;) Thanks in advance.
Here's the change I propose:
This is the new database structure for Users node:
"Users" : {
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"name" : "Sagar Khan",
"phone" : 7276273667
},
..
}
And the contacts of the user "Sagar Khan" will be stored in another node called Contacts under that user's UserID (EXlzg1COUbOhQjwPCGbS1NRdp5H3) :
"Contacts" : {
"EXlzg1COUbOhQjwPCGbS1NRdp5H3" : {
"Contact1":{
"name" : "Sameer",
"phone" : 7276273000
},
"Contact2":{
"name" : "Alice",
"phone" : 7276273600
},
...
},
//other user id with their contacts
...
}
I suspect that the user ID (eg: EXlzg1COUbOhQjwPCGbS1NRdp5H3) is taken from a logged in user, using:
mAuth.getCurrentUser().getUid();
Therefore, to get the contacts of a logged in user you can query the database like this:
DatabaseReference mUserContactsRef = FirebaseDatabase.getInstance().getReference().child("Contacts").child(mAuth.getCurrentUser().getUid(););
mUserContactsRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot userContact : dataSnapshot.getChildren()){
Contact contact = userContact.getValue(Contact.class);
//add each contact to an arraylist and use it to populate a list of contacts
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
You can add each contact object to an ArrayList and use it to populate a list. The key is the User ID, you can access anything related to a user using the UserID.
This is the approach I recommend and what I have used in the past successfully for similar scenarios.

Firebase multiple where clauses using equalsTo

I have a list of all the keys I want to download from Firebase. For this I'm using this code:
Query newUidsQuery = FirebaseDatabaseHelper.getUsersReference();
newUidsQuery.orderByChild(DATABASE_NODE_USER_UID);
for (String uid : uidList) {
newUidsQuery.equalTo(uid);
}
newUidsQuery.addListenerForSingleValueEvent();
This is my current structure:
{
"users" : {
"5mvsiNKz2hO4rmcDDNskv855dkB3" : {
"contacts" : [ "GG8JeRNOIhb1qloZb4oCAb7Jd593", "gc0ci7Jgu2QpVYFbeiMJfVy1WHP2" ],
"contactsHash" : -224276455,
"email" : "lung.razvan#yahoo.com",
"name" : "Razvan Cristian Lung",
"photoUrl" : "https://lh5.googleusercontent.com/-bItm3-ieAtU/AAAAAAAAAAI/AAAAAAAALZo/mtPyAMohOvg/s96-c/photo.jpg",
"uid" : "5mvsiNKz2hO4rmcDDNskv855dkB3"
},
"GG8JeRNOIhb1qloZb4oCAb7Jd593" : {
"contactsHash" : 1,
"email" : "andralung#yahoo.com",
"name" : "Andra Florina Lung",
"photoUrl" : "https://lh4.googleusercontent.com/-po2yelyi3mY/AAAAAAAAAAI/AAAAAAAAQ5s/ROefxP6Q1oA/s96-c/photo.jpg",
"uid" : "GG8JeRNOIhb1qloZb4oCAb7Jd593"
},
"gc0ci7Jgu2QpVYFbeiMJfVy1WHP2" : {
"contactsHash" : 1,
"email" : "lung_razvan2100#yahoo.com",
"name" : "Lung Razvan",
"photoUrl" : "https://scontent.xx.fbcdn.net/v/t1.0-1/p100x100/15390976_1192204140865562_3397773349261436244_n.jpg?oh=d61795a8df67d3e9c5ddf60557e9e60c&oe=59270863",
"uid" : "gc0ci7Jgu2QpVYFbeiMJfVy1WHP2"
}
}
}
The problem is that when I try to get only the entries with the specific key I also get the other entries that have that key as a value in the "contacts" field.
When you call orderBy... or other methods, it returns a new query. So you're now creating a new query for each uid that you then don't use. To keep it, you'd need newUidsQuery = newUidsQuery.equalTo(uid).
But that won't solve the problem yet, because a query can only order/filter on a single property and value. See Query based on multiple where clauses in firebase.
Better news is that this doesn't matter much here, since you can just retrieve the items one at a time. Unlike what you might expect, that's not significantly slower than retrieving them in one go. See Speed up fetching posts for my social network app by using query instead of observing a single event repeatedly or watch this episode of #AskFirebase: https://youtu.be/66lDSYtyils?t=1m49s

Firebase - Querying from FirebaseListAdapter in Android [duplicate]

This question already has an answer here:
Firebase query if child of child contains a value
(1 answer)
Closed 6 years ago.
What is the proper way to query for every Comment (POJO) attached to a Photo (POJO) in Android. In Firebase, I have the following structure for a photo collection:
"photos" : {
"-KaeuYf9jXcy4oqpRqbi" : {f
"entities" : {
"type" : {
"image" : {
"bucket" : "bucket",
"prefix" : "https://s3-us-west-2.amazonaws.com/",
"suffix" : "image.jpg"
}
}
},
"stats" : {
"liked" : 0
},
"text" : "Person Detected!",
"timestamp" : 1484631194257
}
}
and for comments collection:
"comments" : {
"-KdE6Hwua8d6sBQimPos" : {
"attachphoto" : {
"-KaeuYf9jXcy4oqpRqbi" : true
},
"attachuser" : {
"-KaeuYHjkdf9okflslf" : true
},
"displayName" : "Gary",
"text" : "ok",
"timestamp" : 1487385995844
},
"-KdE6IPc-NL-6zGkwXq3" : {
"attachphoto" : {
"-KaeuYf9jXcy4oqpRqbi" : true
},
"attachuser" : {
"-KaeuYHjkdf9okflslf" : true
},
"displayName" : "Thomas",
"text" : "ok",
"timestamp" : 1487385997735
}
}
In Android I'm using a FirebaseAdapter, but I am having trouble defining a proper Query that would only retrieve comments attached to a specific photo. I have the key of the Photo
FirebaseListAdapter adapter = new CommentAdapter(this, Comment.class, R.layout.item_comment, QUERY){
#Override
protected void populateView(View v, Comment model, int position) {
if(model.getDisplayName()!=null) {
String[] name = model.getDisplayName().split(" ");
((TextView) v.findViewById(R.id.id)).setText(name[0]);
}
((TextView) v.findViewById(R.id.content)).setText(model.getText());
}
};
I thought I could define something like:
final FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference commentsRef = database.getReference("comments");
Query query = commentsRef.orderByChild("attachphoto").equalTo()
But I'm having some disconnect on how to finish this. First project using Firebase, so any help/tips would be much appreciated!
Firebase is rather noSQL, therefore there are limits which one has to work around... especially when designing the data-structure. for example, in this case it might make sense to add the ids of the related users & comments (or even the related comments altogether) into a nested node of the structure, which represents the photo. there are other ways to get there - while one always needs to consider how to look up the details later on (because the structure dictates which queries are possible and which not).

Confusing About Firebase startAt()

I'm trying to make android app with firebase, i want use search feature on firebase using startAt(). But the result make me confused.
I have some firebase data like this.
{
"siswa" : {
"100" : {
"id" : 100,
"nama" : "Sucipto"
},
"101" : {
"id" : 101,
"nama" : "Tomo"
},
"102" : {
"id" : 102,
"nama" : "Fitri"
},
"103" : {
"id" : 103,
"nama" : "Sumini"
},
"104" : {
"id" : 104,
"nama" : "Eko"
},
"106" : {
"id" : 106,
"nama" : "Sulastri"
}
}
}
My sample query
// Setup Firebase
final FirebaseDatabase database = FirebaseDatabase.getInstance();
// Firebase siswa ref
final DatabaseReference siswaRef = database.getReference("siswa");
// Query
Query suciptoQuery = siswaRef.orderByChild("nama").startAt("Sucipto");
The result:
D/Query Sucipto: Nama : Sucipto
D/Query Sucipto: Nama : Sulastri
D/Query Sucipto: Nama : Sumini
D/Query Sucipto: Nama : Tomo
I'm try another test query
Query suciptoQuery = siswaRef.orderByChild("nama").startAt("Su");
Result : Same as above
Another Query :
Query suciptoQuery = siswaRef.orderByChild("nama").startAt("Tomo");
or
Query suciptoQuery = siswaRef.orderByChild("nama").startAt("To");
Result:
D/Query Sucipto: Nama : Tomo
I'm searching about this topic on SO, but still don't have any solution.
I checked out the startAt() docs and it the logic is quite confusing. But if I do understand it correctly (Yep, not entirely sure, but gonna post ahead, it might help).
In your first try, the starting value is "Sucipto", I think this indicates that succeeding words/strings that are lexicographically greater, are subject included. As you can see in the result, among of the other child that are all in the reference, Eko and Fitri were not returned, since alphabetically, 'S' is far after 'F' and 'E'.
You can verify this trying to add another value, let's say "Sucipta" is included. If you run the query again where startAt()s value is "Sucipto", the return value would still not include "Sucipta" since the last letter of "Sucipta" is higher (or alpahabetically first (a,b,c....) sorry, I just can't find a good term).
I think this might help, you can check out the Firebase Retrieving Data docs for more detailed description. In an example, they also used a letter instead of a number.

Categories

Resources