I have a collection called 'Skate' is it possible to get all data from her document? for example as in the photo the data of the two parks
fireStore.collection("Parks").document("PracasGravatai").collection("Skate").document().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if(documentSnapshot.exists()) {
String endereco = documentSnapshot.getString("Endereco");
String nome = documentSnapshot.getString("Nome");
Log.i("LOG: ",endereco);
Log.i("LOG",nome);
textView.setText("Nome: "+nome+ "Endereço: "+endereco);
A collection contains documents. Right now you call document(), which means that you're creating a reference to a new, empty document. So the get() call after that then returns a snapshot to a non-existing document.
To load a specific document, you'll need to know its ID. Once you do, you can load it by calling get on the DocumentReference:
fireStore.collection("Parks").document("PracasGravatai")
.collection("Skate").document("theIdOfTheDocument").get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
If you want to load all documents in the Skate collection for PracasGravatai, you can do so by calling get on the collection:
fireStore.collection("Parks").document("PracasGravatai")
.collection("Skate").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());
}
}
});
Both of these cases are covered in the Firebase documentation on getting data from Firestore.
Related
Trying to make a query. But need to find the document if i dont know the parent key of it. So in my db i want to find user by name when i dont know uid.
My db below
Request code
users.whereEqualTo("name", "DavidMells")
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
//Here size is 0 nothing found
int size = task.getResult().size();
for (QueryDocumentSnapshot document : task.getResult()) {
FsUser fsUser = document.toObject(FsUser.class);
String testingValue = fsUser.getCountry();
Log.d("log", document.getId() + " => " + document.getData().get("country"));
}
} else {
Log.d("log", "Error getting documents: ", task.getException());
}
}
});
The declaration of reference
private CollectionReference users = FirebaseFirestore.getInstance().collection(Consts.USERS_DB);
The constant is
public static final String USERS_DB = "Users";
I dont know... Maybe this too simple... but I don't see other option, as the code seems to be proper:
Looking on the screenshot I noticed that there is space after DavidMells in the database, but not in code...
I'm trying to grab subcollections using Firestore's .collectionGroup function however it doesn't seem to be firing at all. It should be returning at least one document found since its status is "Accepted" however when I run debug, it seems to skip over the function and doesn't return any kind of error or any of my logs.
When I run it normally, not in debug mode, it returns "onComplete: found no book reservations for this book"
I also was not prompted initially to create the composite index as is normally done with a singular index field when a new collection group query is first executed so I've attempted to make my own although I'm pretty sure it's not working correctly.
Any help or guidance is appreciated on how to solve this.
my firebase db setup is:
Collection:"Books"
-->subcollection:"bookPendingRequests"
here is a debug screen show to show that it is reading the correct bookFirebaseId
here is a markup of the firebase set up to illustrate what it should be reading.
here is my collectionGroup index:
Here is my code which is set to start at onCreate()
private void loadBookReservationDates() {
getIncomingIntent();
bookPendingRequests = firestoreDB.collectionGroup("bookPendingRequests")
.whereEqualTo("bookRequestParentId", bookFirebaseIdString)
.whereEqualTo("bookReservationStatus", "Accepted");
bookPendingRequests.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.getResult().size() < 0) {
for (int i = 0; i < task.getResult().size(); i++) {
String dates = task.getResult().getDocuments().get(i).get("bookReservationDates").toString();
Log.d(TAG, "onComplete: dates: " + dates);
}
} else {
Log.d(TAG, "onComplete: found no book reservations for this book");
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, "onFailure() returned: " + e);
}
});
}
I am making an app that will listen to new document addition to Firestore collection. I have tried look at Firestore documentation, but doesn't work for my specific problem.
Here is my code listen to document updata
FirebaseFirestore.getInstance().collection("users/" + companyID + "/trips").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot querySnapshot, #Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "Listen failed.", e);
return;
}
if (!querySnapshot.isEmpty()){
for (QueryDocumentSnapshot qds : querySnapshot){
tripList.add(qds.getId());
}
showTripList();//update trip list view
}
}
});
Show the list to the ListView
public void showTripList() {
ListView tripListView = findViewById(R.id.tripList);
if (tripList.size() != 0) {
ArrayAdapter arrayAdapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, tripList);
tripListView.setAdapter(arrayAdapter);//show trip list on screen
} else {
TextView noTripTxt = findViewById(R.id.noTripTxt);
noTripTxt.setVisibility(View.VISIBLE);//show "no trip has been made yet" text to user
}
}
The logcat shows NullPointerException at this two line
FirebaseFirestore.getInstance().collection("users/" + companyID + "/trips").addSnapshotListener(new EventListener<QuerySnapshot>()
tripList.add(qds.getId());
Here the code that is work for me
FirebaseFirestore.getInstance().collection("users/" + companyID + "/trips")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "Listen failed.", e);
return;
}
tripList.clear();//clear the ArrayList, because this method get all the document id instead of
//the one that just created
for (QueryDocumentSnapshot doc : value) {
if (doc.getId() != null){
tripList.add(doc.getId());//store the document IDs to ArrayList
Log.d(TAG, "Retrieved data: " + doc.getId());
}
}
showTripList();//show trip name to listView
}
});
The code you shared seems to try and listen to the trips subcollection of a specific companyId. But the way you build the path to that collection seems suspicious:
collection("users" + companyID + "trips")
The total path should be users/${companyID}/trips, so it's more likely that the code should be:
collection("users/" + companyID + "/trips")
Without the / your code is listening to a top-level collection users${companyID}trips, which doesn't exist. So that would explain why you're not getting any results.
Note that you can easily prevent such string concatenation problems, by using the more explicit API variant:
collection("users").doc(companyID).collection("trips")
While that last variant is a bit longer, it removes the chance of making simple string concatenation mistakes.
With the collection path fixed, your code will be listening for the data in a subcollection. So it will match multiple documents, and get a QuerySnapshot as shown in the documentation on listening to multiple documents in a collection.
I am trying to create a map of objects in my firestore database using key->value pairs.
The idea is to have a map of room objects within my Properties documents where living room would be the key and the object that value. Like the image below
I am getting lost with the correct way to add the objects into firestore as the rooms map is already there so how do I add a key->value pair into it ??
I also need to perform the search I have in the below code so I can grab the Properties document and add the objects into the room map field
FirebaseFirestore db = FirebaseFirestore.getInstance();
final CollectionReference propertyRef = db.collection("Properties");
final Room room = new Room(roomName, feet, inches, imageUrl);
propertyRef.whereEqualTo("propertyId", propertyId).get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot doc : Objects.requireNonNull(task.getResult())) {
propertyRef.document(doc.getId())
-----> .update("rooms", ""+roomName+"", room);
Log.d(TAG, "Firebase Success= " + imageUrl);
Toast.makeText(CreatePropertyActivity3.this, "Property Created", Toast.LENGTH_LONG).show();
exProperties();
}
} else {
Toast.makeText(CreatePropertyActivity3.this, "Error check log", Toast.LENGTH_LONG).show();
}
}
});
Use the document(String) method on the db, which as per docs will create the document if it does not exist (https://firebase.google.com/docs/firestore/manage-data/add-data)
Map<String, Object> room = new HashMap<>();
room.put("feet", "...");
...
db.collection("rooms").document("the new room id")
.set(room)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
...
}
})
.addOnFalureListener(...)
This is if you know the IDs of your documents, or want to set the ID yourself. If so, you can replace the argument passed to .document(...) before adding a new item. Alternatively, you could use the add() method which will create a new document with an auto-generated ID for you.
In your case, it seems as though you are setting your own meaningful ids (e.g. livingroom, kitchen) and you should be changing the propertyId variable before adding a map. However, that is redundant since you already have an attribute (i.e. name) that describes the room. So use add() and avoid querying for a document that would not exist to begin with:
final HashMap<String, Object> newRoom = new HashMap<>();
newRoom.put(roomName, room);
...
propertyRef.add(newRoom)
.addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
#Override
public void onSuccess(DocumentReference documentReference) {
Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.getId());
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error adding document", e);
}
});
In fact, because you were using whereEqualTo you were always fetching a reference to the same document and overwriting its content. Just use the add() functionality and check the docs for more examples. Hope that helps!
In my Firestore database I have a data structure like this:
Units > Unit 1-15 > Words > Documents of words
I want to get the words in each unit.
I want to get the words in unit x after I have fully retrieved the words from unit x-1
I thought about making a method that gets the words from a specific unit and returns true once it's done, so in the main program I can check whether the method has returned true, I can get the words from the next unit.
I tried to use onSuccessListener/onCompleteListener but no avail
I'm getting the words in this way: (Works fine)
String mainCollection = "Units";
String document = "Unit " + unitNumber;
String subCollection = "Words";
CollectionReference docRef = firebaseFirestore.collection(mainCollection)
.document(document).collection(subCollection);
docRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot queryDocumentSnapshot : task.getResult()) {
Word currentWord = queryDocumentSnapshot.toObject(Word.class);
wordsDatabase.wordDao().insertAWord(currentWord); //Inserts the words to Room database table
}
}
}
});
over 500 document in every Words collection so it may takes some time with weak internet connection
You'd typically do this by declaring a function that invokes itself:
int unitNumber = 1;
String mainCollection = "Units";
String document = "Unit " + unitNumber;
String subCollection = "Words";
getWordsFor(1);
public void getWordsFor(int unitNumber) {
CollectionReference docRef = firebaseFirestore.collection(mainCollection)
.document(document).collection(subCollection);
docRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot queryDocumentSnapshot : task.getResult()) {
Word currentWord = queryDocumentSnapshot.toObject(Word.class);
wordsDatabase.wordDao().insertAWord(currentWord); //Inserts the words to Room database table
}
// if there are more units to read, kick off the next one
if (unitNumber < 15) {
getWordsFor(unitNumber+1);
}
}
}
});
}
So we kick it off with getWordsFor(1) and then after it's done reading, the function check if there's more work to do, and reinvokes itself if that's the case.