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.
Related
I'm working on an app that contains USERs and EVENTs.
Each event has several users and each users has several events.
In Firebase, both events and users as "details" key(see json below), and those details are duplicate so all the event users has the details of the event, so in my main activity I have a recyclerview that shows those events easly (and the same way for users list inside event activity.
To sync all those duplicates I use firebase functions.
Now I want to move ti firestore but I'm not sure how should it be.
From what I see I can have list of users IDs in event document and then do a query for all events with user.id = current_user_id.
The issue is that I have more fields per user (expenses, and I want to add more) So either I have also subcollection for each user, or have more complicate list.
Can I query the events according to their subcollection id?
I will appreciate any help with that.
The current Json:
{
"events" : {
"-L7v0K***" : {
"average" : 110,
"details" : {
"date" : {
"date" : 1520354933426
},
"location" : "Tel Aviv",
"name" : "test"
},
"items" : {},
"require_transactions" : [ {}],
"totalexpenses" : 220,
"users" : {
"ARKuwgrDHcNnXHoPlCgIBXOObjD3" : {
"details" : {
"uid" : "ARKuw***",
"userEmail" : "r***g#walla.com",
"username" : "R** G***"
},
"expenses" : 20
},
"pDFtk***" : {}
},
"-L84Gg***" : {}
}
},
"users" : {
"ARKuw***" : {
"details" : {
"uid" : "ARKuwg***",
"userEmail" : "r***g#walla.com",
"username" : "R** G***"
},
"events" : {
"-L7v0Kx***" : {
"date" : {
"date" : 1520354933426
},
"location" : "Tel Aviv",
"name" : "test"
},
"-L97_3***" : { }
},
"TAJK6***" : {}
}
}
}
Firebase is pretty close to firestore, i also started everything with firebase realtime and moved to firestore, to have more complex queries.
So, as i understood, you will have two primary collections, you can create them by:
firebase.firestore().collection('users')
firebase.firestore().collection('events')
inside users you will have a subcollection called events to trigger all events a specific user have, so it will be like this:
firebase.firestore().collection('users').doc(userId).collection('events')
To make queries, for example, to get all events that a specific user is attending you can type:
firebase.firestore().collection('users').doc(userId).collection('events').get()
(here you can do filters like limiting, 'where', byId... by 'field equals to'... all of this is the documentation)
this will return all eventsId that are in the collection he attended.
Remember to work thinking on scale to get lower cost.
If you can explain more the task you need i can work in a solution.
Documentation of firestore is very easy.
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.
This question already has answers here:
Query based on multiple where clauses in Firebase
(8 answers)
Closed 5 years ago.
Solution:
As Frank already states, I had to create a separate filed for this sorting to work. As suggested, I created a filed "sortField" which combines the
"clubKey" + "_" + "startDate"
To modify my existing data sets, I made a quick java script function like this:
function createTestDataSet(){
evd = dbAllEventsListRef;
evd.on('child_added', function(snap, previous){
console.log(snap.val());
data = snap.val();
data.sortField = data.clubKey + "_" + data.startDate;
testDiv = document.getElementById("divCarSummary");
testDiv.innerHTML = testDiv.innerHTML + "<br/>"+data.sortField;
evd.child(snap.key).set(data);
});
}
I tested this using the following code:
function testSort(){
key = "manualClubKey-1";
testEvents = dbTesting.child('eventList').orderByChild("sortField").startAt(key+"_").endAt(key+"a");
testEvents.on('child_added', function(snap, previous){
data = snap.val();
testDiv = document.getElementById("divCarSummary");
testDiv.innerHTML = testDiv.innerHTML + "<br/>"+data.startDate+", "+data.name+", "+snap.key+", "+data.clubKey;
console.log(snap.val());
});
}
The tricky part was, that the manual for "endAt" states:
The ending point is inclusive, so children with exactly the specified value will be included in the query
But this does not seem to be true.
If I give the same value for startAt() and endAt(), I get no results.
So I modified the query, that I look for the "clubKey" + the separator. For the Separator I gave a character right after the "_". thus it works like a charm.
I modified my android Code, so every time the startDate, or the clubKey is written, I update the "sortFiled", small change, works like a charm.
Original Question
I have some event data.
Sample data:
{
"modeltruckerManualEventID-96" : {
"canceled" : false,
"clubKey" : "manualClubKey-1",
"endTime" : "17:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-06-17",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-97" : {
"canceled" : false,
"clubKey" : "manualClubKey-2",
"endTime" : "17:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-06-17",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-98" : {
"canceled" : false,
"clubKey" : "manualClubKey-2",
"endTime" : "16:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2012-03-11",
"startTime" : "10:00:00"
},
"modeltruckerManualEventID-99" : {
"canceled" : false,
"clubKey" : "manualClubKey-1",
"endTime" : "16:00:00",
"eventOpenForWeightData" : false,
"link" : "",
"locationID" : "manualLocationID-4",
"name" : "Fahrtag TuHaKi",
"startDate" : "2011-11-27",
"startTime" : "10:00:00"
}
}
I now want to filter, so I only get events from one "clubKey"
which I could achieve using:
.orderByChild("clubKey").equalTo("manualClubKey-1")
That works fine.
But is there any way, that I can order the results also by child "startDate"?
So I want to have the filtered results ordered by startDate finally.
As far as I know this does not work.
I use Firebase on Android with Firebase UI.
Any Ideas how to achieve that?
I do not want to restructure the data or duplicate it further.
Hope there is a way, maybe force the ordering already on storage?
If you want to orderByChild(especificdate), is not possible without restructuring the data.
However, lets say you want to get the latest added nodes, just use limitToLast(numberOfChildren)
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
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).