I want to use the following code to get data from firestore that is sorted according to the date the document was updated on:
fun getQuery(groupID: String): Query {
val path = FirestorePath()
return path.getTaskCollectionRef()
.orderBy(ActionTask.FieldNames.taskUpdatedOn.name, Query.Direction.DESCENDING)
.whereEqualTo(ActionTask.FieldNames.taskGroupID.name, groupID)
.whereEqualTo(ActionTask.FieldNames.taskOpen.name, true)
}
The problem is that the .orderBy() causes my app to display data from documents that are deleted (existed previously, now deleted).
When I remove the .orderBy(), I see the correct data in my app.
This is due to the offline mode of Firestore being active by default in your code. You should turn if off in order to avoid getting responses from the cache instead of your database.
You can find more information about the offline mode and how to disable it for Android over at this document
Hope you find this useful!
Related
I am new to Firestore and I am developing an android app where I am loading comments in Recycler View.
Below is sample data class for comment.
data class Comment(
val id: String,
val text: String,
val user: DocumentReference
)
Currently I am using this below code in onBindViewHolder in adapter
comment.userId.get()
.addOnCompleteListener {
if (it.isSuccessful) {
val u = it.result.toObject(User::class.java)
user = u.name
binding.userTv.text = user
}
}
binding.commentTv.text = comment.text
I have to explicitally run Task<TResult> every time to fetch the user in adapter.
I am looking for a better way to retrieve user from comment to display username is a single query.
Typically when dealing with usernames that may update regularly, traditionally you would store the raw user name string in each document which requires heavy read/writes to keep it updated. Instead, it has been found better to store them in a master document/collection that assigns all user UID's with the display name as the value, allowing you to look up any user UID and know it from one source of truth.
This has been made easier with the new Bundle Feature which allows all apps to preload documents in your app to prevent the need to fetch them every time. The only catch is you will need to retrieve the data when a new user isn't in their cached data yet or have a dedicated source for all new users to reduce overhead in those situations.
Source: Data Bundles
Let's say that I have a document like this:
Document {
tags: list<Int> {0,1,2}
}
I want to change it to this:
Document {
tags: list<String> {SEASON, TRAINING, TOURNAMENT}
}
I have active users which uses the list of ints, How do I create a migration in Firestore for this problem?
One solution I have in mind is to make 2 migrations:
For creating a new tags called tagsStrings.
For deleting all users who still have tags.
But can I make it in 1?
I was unable to find documentation for this, on https://cloud.google.com/firestore/docs/manage-data/move-data
Thanks in advance
Firestore does not have a "migration" like SQL databases. The only way to modify data in existing documents, in bulk, is to:
Query for the documents to change
Iterate the results
Update each document with new values
Each one of these tasks should be straightforward.
You might also consider lazily updating each document as each are individually read during the normal course of your app's usage. So, if your app reads a document in the old format, immediately update it to the new format.
It's often helpful to have a dedicated field in each document to indicate which version of data that's contained within. So, initially set v=1 in each document, assign v=2 to mean that the document has strings instead of numbers for tags, then use that number to determine which documents have yet to be migrated.
I keep a local copy of a simple database in user's phone. This way the app can be used offline. I want to check with firebase server from time to time and update the local database if there is any change. So I need to know last action (insert, update, delete, etc.) time in a specified location in Firebase database. Is that possible? Or should I implement my own mechanism?
The Firebase Database does not store informations like the timestamp for CRUD operations that are performed. Because of that, you need to store this kind of data yourself with your own mechanism. So, you need to create a new field for each child you want to trace and change the value of the TIMESTAMP every time a action is performed. The best practice is to save your data as a TIMESTAMP like this: ServerValue.TIMESTAMP. Note, that when you are saving the TIMESTAMP, you are saving as a Map and when you are retrieving, you are retrieving it as a long. To set the TIMESTAMP, i recomand you using the following code:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Map map = new HashMap();
map.put("time", ServerValue.TIMESTAMP);
ref.child("yourNode").updateChildren(map);
To get you data back, i recomand you using the following method:
public static String getTimeDate(long timeStamp){
try{
DateFormat dateFormat = getDateTimeInstance();
Date netDate = (new Date(timeStamp));
return dateFormat.format(netDate);
} catch(Exception e) {
return "date";
}
}
This is possible but you shouldn't
Firebase already has offline capabilities, is very simple to use. Is a 2 steps process:
Set offline capabilities on
Set what you want to keep track ass offline
This is the official documentation
In code this is done something like this:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores");
scoresRef.keepSynced(true);
There is big temptation to use:
FirebaseDatabase.getInstance().getReference().keepSynced(true);
Trying to keep everything sync by syncing the root reference doesn't work, you have to be specific, at least at 1 level parent.
The syncing when the connection is resumed is automatic, the user has to open the app though, flawless.
Now, if you still insist on doing this, then what you have to do is set ServeValue.TimeStamp
In the same link provided above, you can find how to set the server timestamp, here is the direct reference.
Later you can sort by that timestamp, here is a more detailed answer
pretty straightforward question. im making an android app that uses firebase authentication for users to connect with email and password an also the firebase realtime database service.
i wanted to know if i can check through android studio how many people are currently connected to my database(through Firebase Authentication)
thanks in advance!
This is an old question but in case someone is searching for a solution, I've found some info on Firebase docs:
https://firebase.google.com/docs/firestore/solutions/presence
It's very simple. Every time a user is connecting to your app, add him in a Firebase category, named users. Then you can query on that category to see the exact number of users using the following line of code:
int numberOfUsers = dataSnapshot.getChildrenCount();
var database = firebase.database();
// connecting users
var connectionsRef = database.ref("/connections");
var connectedRef = database.ref(".info/connected");
// Number of online users is the number of objects in the presence list.
// When the client's connection state changes...
connectedRef.on("value", function(snap) {
// If they are connected..
if (snap.val()) {
// Add user to the connections list.
var con = connectionsRef.push(true);
// Remove user from the connection list when they disconnect.
con.onDisconnect().remove();
}
});
// When first loaded or when the connections list changes...
connectionsRef.on("value", function(snapshot) {
// Display the viewer count in the html.
// The number of online users is the number of children in the connections list.
console.log("numers of players are:"+ snapshot.numChildren());
$(".displayDiv").text(snapshot.numChildren());
I have a small firebase database with a list. How can I get the last inserted value of the list?
The elements of the list have as key a date string, example:
2016_05_29 --> data
2016_05_30 --> data
2016_05_31
2016_06_01
2016_06_02
2016_06_03
2016_06_10
2016_06_11
2016_06_12
2016_06_13
2016_06_14
2016_06_15
2016_06_16
2016_06_17
2016_06_18
2016_06_19 //returned value
2016_06_20
2016_06_21
2016_06_22
2016_06_23 //expected value
I am try to get the last value of this list, so 2016_06_23 but for some reason it returns this 2016_06_19 whatever key/order system I use:
Query dateMaxRef = ref.orderByKey().limitToLast(1); //this returns always 2016_06_19 instead of 2016_06_23
dateMaxRef.addListenerForSingleValueEvent(new ValueEventListener()
....
Any idea?
I faced the same issue and for me the reason was because the query was not using the latest data from firebase and instead relying on internal cache. Using .keepSynced(true) on the query fixed it for me. Below is the sample code -
Query causeListPath = mFirebase.child(PATH_CAUSE_LIST).child(SELECTED_CITY)
.child(SELECTED_COURT_CODE).limitToLast(1);
// If user wants un-cached data, force sync
if (!useCache) causeListPath.keepSynced(true);
causeListPath.addChildEventListener(new ChildEventListener() {
...
});