How to check if Cloud Firestore collection exists? ( querysnapshot) - java

I'm having trouble with checking if my collections exists in Firestore database.
When I was working with Firebase Realtime database i could have used:
if(databaseSnapshot.exists)
Now with Firestore I wanna do the same.
I have already tried
if (documentSnapshots.size() < 0)
but it doesn't work.
Here is the current code:
public void pullShopItemsFromDatabase() {
mShopItemsRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
ShopItem shopItem = document.toObject(ShopItem.class);
shopItems.add(new ShopItem(shopItem.getImageUrl(), shopItem.getTitle(), shopItem.getSummary(), shopItem.getPowerLinkID(), shopItem.getlinkToShopItem(),shopItem.getLinkToFastPurchase(), shopItem.getKey(), shopItem.getPrice(),shopItem.getVideoID()));
}
if (shopItems != null) {
Collections.sort(shopItems);
initShopItemsRecyclerView();
}
} else {
Log.w(TAG, "Error getting documents.", task.getException());
setNothingToShow();
}
}
});
}
the function: setNothingToShow();
Is actually what I wanna execute if my collection is empty / doesn't exists.
Please advise!
Thanks,
D.

Use DocumentSnapshot.size() > 0 to check if the collection exists or not.
Here is an example from my code:
db.collection("rooms").whereEqualTo("pairId",finalpairs)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
if(task.getResult().size() > 0) {
for (DocumentSnapshot document : task.getResult()) {
Log.d(FTAG, "Room already exists, start the chat");
}
} else {
Log.d(FTAG, "room doesn't exist create a new room");
}
} else {
Log.d(FTAG, "Error getting documents: ", task.getException());
}
}
});

exists() applies to DocumentSnapshot while you're dealing with QuerySnapshot
Call task.result for getting QuerySnapshot out of Task<QuerySnapshot>.
From that, call result.getDocuments() and iterate through each of the DocumentSnapshot calling exists() on them.

Related

How to get the id for document in collection?

how to get id for document a ?
const name=prod['categ'].value;
const a=db.collection('Categories').whereEqualTo("Name", name);
b=a.id;
You're not yet executing the query, which is necessary to get its ID.
Something like:
const query = db.collection('Categories').whereEqualTo("Name", name);
query.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());
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
The majority of that code is copied straight from the Firebase documentation on getting multiple documents from a collection, so I recommend spending some time studying that.

Firestore: how can read data from outside void onComplete methods

I read data from Cloud Firestore:
firestoreDB.collection("events")
.whereEqualTo("type", eventType)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Event> eventList = new ArrayList<>();
for(DocumentSnapshot doc : task.getResult()){
Event e = doc.toObject(Event.class);
e.setId(doc.getId());
eventList.add(e);
}
//do something with list of pojos retrieved
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
Since onComplete is a void method, how can I get eventList from outside methods?
For example, I tried:
List<Event> ReadCollection()
{
final List<Event> eventList = new ArrayList<>();
firestoreDB.collection("events")
.whereEqualTo("type", eventType)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Event> eventList = new ArrayList<>();
for(DocumentSnapshot doc : task.getResult()){
Event e = doc.toObject(Event.class);
e.setId(doc.getId());
eventList.add(e);
}
//do something with list of pojos retrieved
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
return eventList;
}
It doesn't work since onComplete is a void method. I can read nothing from Cloud Firestore.
You cannot return something now that hasn't been loaded yet. The onComplete() method has an asynchronous behaviour which means that is called even before you are trying to add those objects of type Event to the eventList ArrayList. That's why your list is always empty outside that method. With other words, by the time you are returning the eventList, the data has not finished loading yet from the database, so to solve this, you need to create you own callback in order to wait for the data. So first you need to create an interface like this:
public interface MyCallback {
void onCallback(List<Event> eventList);
}
Then you need to create a method that is actually getting the data from the database. This method should look like this:
public void readData(MyCallback myCallback) {
firestoreDB.collection("events")
.whereEqualTo("type", eventType)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
List<Event> eventList = new ArrayList<>();
for(DocumentSnapshot doc : task.getResult()) {
Event e = doc.toObject(Event.class);
e.setId(doc.getId());
eventList.add(e);
}
myCallback.onCallback(eventList);
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
}
In the end just simply call readData() method and pass an instance of the MyCallback interface as an argument wherever you need it like this:
readData(new MyCallback() {
#Override
public void onCallback(List<Event> eventList) {
Log.d("TAG", eventList.toString);
}
});
This is the only way in which you can use the eventList outside onComplete() method. For more informations, you can take also a look at this video.

Firestore perform delete based on condition [duplicate]

This question already has answers here:
How to delete document from firestore using where clause
(12 answers)
Closed 9 months ago.
Is there a way I can perform a delete on Firestore documents where field1 =x and field2 = y?
I see the delete function but does not come with where.
If I use the transaction then there is get and delete but the get does not seem to accept "where" clause.
I hope I am missing something in the documentation.
Thanks
To achieve this, you need to create the desired query first and then just use the delete() method like this:
FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
CollectionReference itemsRef = rootRef.collection("yourCollection");
Query query = itemsRef.whereEqualTo("field1", "x").whereEqualTo("field2", "y");
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
itemsRef.document(document.getId()).delete();
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
Here's my method for both querying and deleting documents from firestore. First it queries the data, then it deletes it.
Note, this method must be adapted for integer/double values.
public void whereQueryDelete(final String collection, final String field, final String value) {
mFirestoreDatabase.collection(collection)
.whereEqualTo(field, value)
.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());
String idDelete = document.getId();
mFirestoreDatabase.collection(collection).document(idDelete)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully deleted!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error deleting document", e);
}
});
}
} else {
Log.d(TAG, "Error getting documents: ", task.getException());
}
}
});
}

Cloud Firestore - Access Field for Realtime Updates

I am trying to access a field labeled vote_count via Cloud Firestore realtime updates.
Below is my data structure:
Previously, under Firebase Realtime Database, I would .addValueEventListener() and drill down to the "answer." However, with Cloud Firestore, it is a bit more complex.
mStoreSelectedPollRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(final DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
if (e != null){
Log.v("LISTEN", "LISTEN_FAILED");
return;
}
if (documentSnapshot != null){
Log.v("Current Data", String.valueOf(documentSnapshot.getData()));
mStoreSelectedPollRef.collection(ANSWERS_LABEL).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
updatePollResultAnswersDynamically(task.getResult().size(), documentSnapshot);
}
});
} else {
Log.v("Current Data", "Current Data Nulll");
}
}
});
Right now, I am adding a call to .get() within my Snapshot Listener, which seems to be inefficient. I was curious how I would access the:
Total number of answer Documents.
Each individual answer
Given this snippet:
mStoreSelectedPollRef.collection(ANSWERS_LABEL).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
updatePollResultAnswersDynamically(task.getResult().size(), documentSnapshot);
}
});
You can get the total number of answer documents with:
task.getResult().size()
Since you already have this code, I'm not really sure what you're asking. If you're asking if there is a way to get the count without getting the documents, look here: https://stackoverflow.com/a/46555026
To access the individual answer documents, you loop over the query snapshot:
for (DocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}

Firestore - How Can I Get The Collections From a DocumentSnapshot?

Let's say I have a userSnapshot which I have got using get operation:
DocumentSnapshot userSnapshot=task.getResult().getData();
I know that I'm able to get a field from a documentSnapshot like this (for example):
String userName = userSnapshot.getString("name");
It just helps me with getting the values of the fields, but what if I want to get a collection under this userSnapshot? For example, its friends_list collection which contains documents of friends.
Is this possible?
Queries in Cloud Firestore are shallow. This means when you get() a document you do not download any of the data in subcollections.
If you want to get the data in the subcollections, you need to make a second request:
// Get the document
docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
// ...
} else {
Log.d(TAG, "Error getting document.", task.getException());
}
}
});
// Get a subcollection
docRef.collection("friends_list").get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
Log.d(TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(TAG, "Error getting subcollection.", task.getException());
}
}
});

Categories