I have been searching for quite a while now and I can't seem to find anything to help me...
I want to fetch data from a firebase firestore collection that I have in reference (timeEntryTable). In the debugger, I can see that my data is accessed correctly, but when I get out of the method, it seems like everything is gone...
private void getTimes(){
float totalTime = 0;
timeEntryTable
.whereEqualTo("person", "Alexandre")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
TimeEntry timeEntry = new TimeEntry(document.getData());
times.add(timeEntry.getTime());
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
System.out.println("times = " + times);
}
In this snippet, times is a private ArrayList member and TimeEntry is a POJO that has the structure of the documents in the collection.
I can really see in the debugger that times is filled with the right data, but when I call System.out.println("times = " + times);, the value is []... Is there something I am not doing correctly?
Thank you :)
To add to the previous answer that "the first time you can use the results is inside the callback itself", move the "System.out.println("times = " + times);" line right outside underneath your for loop.
Firestore's get() operation, and all of its APIs, are asynchronous and return immediately, before the data is available. Your code continues to execute while the query completes. Some time later, the callback you attached with addOnCompleteListener will be invoked with the results of the query.
The first time you can use the results is inside the callback itself. You can't be certain that any other access to your times array will contain anything. This means that you will have to build your program around these asynchronous APIs instead of depending on line-by-line execution.
Related
i have a collecntion Which Contain Multiple document and i want to fetch higest index document form it
I want to fetch Lat document of Customer_Info
but i dont know it value
and i dont know how to implement orderBy in collections => Document => document_Data
If Bill_ID is same as the document ID, you can use orderBy() and limit(1) to get last document in that collection as shown below:
db.collection("(?)/Business/Customer_Info")
.orderBy("Bill_ID", Direction.DESCENDING)
.limit(1)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
However, you must ensure the field must be a number or the order will not be correct as Firestore orders them lexicographically.
You should avoid using sequential documents IDs and using a timestamp to order documents might be a better idea.
Also checkout:
Limitations of using sequential IDs in Cloud Firestore.
Order and limit data with Cloud Firestore
I'm creating this post as I can't solve my problem with existing ones.
I'm saving the current time on Firestore with :
Map<String, Object> docData = new HashMap<>();
docData.put("Starting date", new Timestamp(new Date()).toDate());
docData.put("Quantification", 3.14569);
userManager.getUsersCollection().document(userManager.getCurrentUser().getUid())
.collection("habits")
.document(selectedHabit)
.set(docData)
Then, I would like to get back the timestamp and use it to count since how many days it's been created. I'm stuck here. The only way I found to access specific data of a document is by doing this :
userManager.getLoggedUserHabitsSubCollection()
.get()
.addOnCompleteListener(new OnCompleteListener < QuerySnapshot > () {#
Override
public void onComplete(#NonNull Task < QuerySnapshot > task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document: task.getResult()) {
Log.d("test", document.getId() + " => " + document.getData() + " => " + document.get("Starting date"));
}
} else {}
}
});
with "document.get("Starting date") I can access my saved date, that's the only thing that I was able to make work to do so. Now I would like to be able to display this Object in a string, and to check differences between dates to know how much time have passed. And here I'm stuck. I see a lot of different answers on forums, like using .toDate() for example, but when I write document.getData().toDate(), it's in red. I tried a lot of things with different ways of writing it, it's always in red and I can't make it work. Any help appreciated.
I see a lot of different answers on forums, like using .toDate() for example, but when I write document.getData().toDate(), it's in red.
DocumentSnapshot#getData() method returns an object of type Map<String, Object>. So there is no way you can add a call to .toDate() on such an object. If you need to get the value of a specific field as a Date object, then you should use the getDate(String field) method, which:
Returns the value of the field as a Date.
Or DocumentSnapshot#getTimestamp(String field) method which:
Returns the value of the field as a com.google.firebase.Timestamp.
Once you have the Date object, you can then calculate the difference between two Java date instances.
I am doing a project for school - android app which registers users to realtime database after it checks if there's a corresponding card number and phone number in a different database in Firestore. At the moment it verifies only the first document, but it wouldn't find the fields if I search for them in other documents.
This is the method I use:
public void checkIfCardExists() {
Query query = cardInfo.whereEqualTo("CardNo", cardNumber)
.whereEqualTo("Phone", userPhone);
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
boolean documentExists;
if (task.isSuccessful()) {
Log.d("QueryResult", "Is query result empty: " + task.getResult().isEmpty());
documentExists = !task.getResult().isEmpty();
}else {
Log.e("QueryResult", "Error getting documents.", task.getException());
documentExists = false;
}
if(documentExists) {
Log.d("QueryResult", "The document exists");
Toast.makeText(com.example.transportticket.RegistrationLeap.this, "Card number found",
Toast.LENGTH_SHORT).show();
userLeap = new UserLeap(userEmail, userPass, userName, userSurname, cardNumber, userPhone);
registerUserLeap(userEmail, userPass);
startActivity(new Intent(RegistrationLeap.this, Empty.class));
}else{
Log.d("QueryResult", "The document doesn't exist or there was an error retrieving it");
Toast.makeText(com.example.transportticket.RegistrationLeap.this, "Card number not found",
Toast.LENGTH_SHORT).show();
startActivity(new Intent(RegistrationLeap.this, Empty.class));
}
}
});
}
And this is how my Firestore database looks like
Firestore database
I added a photo to clarify about finding the first document
If you are using the following line of code:
Query query = cardInfo.whereEqualTo("CardNo", cardNumber)
.whereEqualTo("Phone", userPhone);
It means that you are telling Firestore to return all documents where the CardNo property holds the value of cardNumber AND the Phone property holds the value of userPhone. So if in your collection only one document satisfies this constraint, a single document will be returned. The other documents won't exist in the results. What you are doing now, is called filtering. However, if you want to get all documents, then you should remove both whereEqualTo() calls or directly use cardInfo which is a CollectionReference object. In this way, you aren't filtering anything. A CollectionReference object is basically a Query without any filters.
So using the last solution you can get all documents and you can also create the filtering on the client. This is not a recommended approach because getting all documents, will be very costly. For instance, if you have in your collection 1000 documents, you'll pay 1000 read operations to have them. So it's up to you to decide which one is better for you.
I cant get user recipe Ids to list
I try to query by whereEqualTo and orderBy but on compile firebase suggested me to create indexing, so I did that but it dont give me any results.
for (String mealType : dishTypeList){
userCollectionReference.document(userId).collection("favourites")
.whereEqualTo("mealType", mealType)
.orderBy("dateWhenSetFavourite", Query.Direction.DESCENDING)
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
List<String> favouriteRecipeIds = new ArrayList<>();
for (QueryDocumentSnapshot document : task.getResult()){
favouriteRecipeIds.add(document.toObject(FavouriteRecipeModel.class).getRecipeId());
Log.d(TAG, "LIST LIST: " + favouriteRecipeIds);
}
myFirebaseCallBack.onSuccessCallback(favouriteRecipeIds);
}
});
}
I want to get recipeId whereEqualTo by mealType and ordered by dateWhenSetToFavourites
This is my database:
Are you sure that dishTypeList contains the same dish types that are used in the database? If yes, your code looks fine to me. If all your objects in the database contain the recipe id than the following code should work:
favouriteRecipeIds.add(document.toObject(FavouriteRecipeModel.class).getRecipeId());
Otherwise, a more simpler way of getting the document id would be:
favouriteRecipeIds.add(document.getId());
Beside that, everytime you are getting as a result a Task object, check to see if it is successful:
if (task.isSuccessful()) {
//Your logic
} else {
Log.d(TAG, task.getException().getMessage());
}
And also use the else part of the statement to check for an error message.
considering that multiple whereArrayContains() not working, I have problems with multiple whereEqualTo() on nested HashMap.
I am making simple chat app with firebase and, in some point, I need to determine if chat document from firestore exists for two user ids. My current firestore setup for chat is:
chatId : {
lastMessageText: string
lastMessageTime: long
memberIds: {
userId1 : true
userId2 : true
}
}
My code is:
chatsCollection
.whereEqualTo("memberIds., + currentUser.getUsername() "true") // which is memberIds.userId1
.whereEqualTo("memberIds." + opponentUser.getUsername(), "true")
.get()
.addOnCompleteListener(task -> {
if (task.isSuccessful()) {
if (!task.getResult().isEmpty()) {
// some logic
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
});
but always returns empty result. I checked could firestore and everything is there. What am I missing?
Thanks in advance.
Your code looks like it's maybe trying to compare a boolean in the database with a String. If you have a boolean type field in the database, you should also be using a boolean type value in the query (not a string with quotes around it). Always make sure types match.