Firestore getting or adding spesific data - android

I'm currently using Realtime Database, but I can't find any solution for my question.
My Inventory hierarchy in Realtime Database:
My setValue function: (realtime database)
dbRef.child("inventoryData/inventory/" + gainedItem.getDbId() + "/items/" + gainedItem.getItemId()).setValue(dbInventoryItemClass);
How can I do this in Firestore?
In Firestore, I'm storing my data in a document. But when I want to edit spesific data, I have to download all document - edit - upload again. What I want is that I just want to edit specific data like in Realtime Database.
For example, I want to remove "0" from subList, in realtime database I can remove with:
dbRef.child("inventoryData/inventory/" + gainedItem.getDbId() + "/items/" + gainedItem.getItemId()).setValue(null);
How can I do this in firestore? I can't use this code: ref.collection("users").document(*userId*+"/inventory/0/items/2....").delete();
Is there any way like I used in Firebase?

I'm not entirly familier with what you want to gain, but I'll give it a try.
with a single collection lets call it "ITEMS".
the "ITEMS" collection will hold the dbInventoryItemClass, and because we are using the firestore and not the realtime database, document read is the same regardless of the quantity of data in it (up to a certain limint)
add in dbInventoryItemClass fields like inventoryID
(that you can query with .whereEqualTo("inventoryID",0) to get all items in inventory 0.
you can of course add as may identifications and chain several whereEqualTo's, just make sure to log the exeption given in the OnFailureListiner to get the link to create the index for the chained whereEqualTo query.
as for your question:
As I undestand it, I have to download all inventoryData in Firestore. Is it true?
as far as i know, in firebase firestore when you Query document(s), you'll get ONLY the document you queried (and not any subcollection assosiated with the document)
good luck!

Related

How to get a document from a Cloud Firestore collection based on index?

For developing an Android app in Kotlin, I am trying to find a way to retrieve a document from a Firestore collection based on a certain index and I am not sure how to go about it. For example, if my collection has 50 documents, what would be the best way to retrieve the 10th document so that I can populate text views on my app based on the field values of that document?
Thank you for taking the time to answer my question.
When you add documents to Firestore using the CollectionReference#add() method, you'll see a random document ID that is assigned automatically for each document. If you check the Firebase Console or you try to query a collection programmatically, you will not find any order for the containing documents. This means that there is no index involved. So it's not correct to say, hey Firestore, give me the 10th document, because when you query a collection of 50 documents, the 10th document might be the one you are interested in, but if you add/delete documents, the 10th document won't be the same.
You might think, ok, I can provide my own document IDs, starting from 0 - 49, and when I query the collection I can order them by their document IDs. But, this is not an option, since the document IDs are always strings, and when you order strings, the order is lexicographical.
The best solution I can think of, if you need to get a particular document from a collection, is to add a specific field in that document, so it can be identified very easily. For instance, you can add a particular name or ID for each document, and then you can perform a query that looks like this:
rootRef.collection("users").whereEqualTo("name", "Bhavey")
In this way, you can simply identify each one of the documents in your collection.
To accomplish this, will require some setup.
let's say you have a collection of documents and you want to manage them and find the 10th document, Firestore generates unique hash id's that are based on the timestamp making them have an inherent order based on the time they were generated.
All you need to do is manage a dedicated document in the parent of this collection that contains an array of all document id's in the subcollection.
reading this document and it's array would get you an ordered list of documents without incurring the additional reads of the documents as other methods, even listing the ID's requires 1 read each.
on the successful operation of it being added, you can use a Cloud Function onCreate trigger to push the document id to the master array and the same with onDelete. But if cloud Functions are not available or you want to brute force it from the client, you can do the following:
db.collection("users")
.document("uid")
.collection("posts")
.add(city)
.addOnSuccessListener { documentReference ->
db.collection("users")
.document("uid")
.update("index", FieldValue.arrayUnion(documentReference.id))
.addOnSuccessListener { Log.d(TAG, "Index Added!") }
.addOnFailureListener { e -> Log.w(TAG, "Index Error", e) }
}
.addOnFailureListener { e -> Log.w(TAG, "Error source document", e) }
Cloud Functions sources:
trigger_a_function_when_a_new_document_is_created
trigger_a_function_when_a_document_is_deleted
*note: to scale this past 1mb firestore document limits - you will need multiple index documents with a counter and to manage this with Cloud Functions. The end result should double your writes without crippling your reads

Display images from Firebase Storage order by date added in Android

I am trying to display images from Firebase's storage in my Android app inside a GridView.
I have done that, however, the images are displaying in an unknown order, and I have noticed that there is a 'Last modified' column inside Firebase's storage when I upload the images to it.
My question is: is there a way that I could sort the images inside the GridView in order to display them according to that date? (for example, the last one added, would have the latest 'Last modified' date and would be viewed first and such...)
This is my code:
val listRef : StorageReference = FirebaseStorage.getInstance().reference.child("images/posts/$userName")
val fileNameList: ArrayList<String> = ArrayList<String>()
listRef.listAll()
.addOnSuccessListener { it ->
it.items.forEach{
fileNameList.add(it.name)
}
gridView?.adapter = ImageRecyclerAdapter(activity, fileNameList,userName)
}
Note: the code is in Kotlin
I have looked everywhere and couldn't find anything that helps.
Any help is appreciated, thank you :)
According to the official documentation regarding StorageReference's listAll() method:
List all items (files) and prefixes (folders) under this StorageReference.
You might not be interested in listing folders within the reference you are pointing to.
That been said, the best option that you have is to store the URLs in a database. Such a database can be either Cloud Firestore or Firebase Realtime Database. This means that each object should have at least two fields, one for the actual URL and one for a timestamp. Please see in my answer from the following post how you can add a timestamp to Firestore:
ServerTimestamp is always null on Firebase Firestore
Is in Java, but you can simply convert it to Kotlin. Once you have all URLs in place, you can create a query and order the URLs according to the date. In Firebase Realtime Database the default order is ASCENDING, but below is how you can reverse the order:
How to arrange firebase database data in ascending or descending order?
While in Firestore, you can simply pass the desired direction to Query's orderBy(String field, Query.Direction direction) method.

Firebase Firestore OR query (Android Studio)

I've been trying to find a query for almost 2 days now
I want to search id (current user id) from the document 4 fields (customer1,customer2,customer3,customer4)
Here is the firestore document picture
tried this query
final Query userQuery = collectionReference
.whereEqualTo("customer1",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer2",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer3",firebaseAuth.getInstance().getCurrentUser().getUid())
.whereEqualTo("customer4",firebaseAuth.getInstance().getCurrentUser().getUid());
but this only shows up if the current ID is present in all 4. Is there any easier way to do this.
You can do that by using a field that is an array containing the uids you want to test, and then applying array-contains on it. In your case:
In your case:
customer: [customer1, customer2, customer3, customer4]
collectionReference
.where("customer ", "array-contains", firebaseAuth.getInstance().getCurrentUser().getUid())
Firestore does not support logical OR queries among mulitple fields. So, what you're trying to do is not possible with a single query using the database structure you have now. You would have to perform multiple queries and merge the results in the client.
If you want to be able to use a single query, you will have to change your database. One option is to put all the customers into a single array field and use an array-contains query to find a customer in that field.

Firebase Realtime database Array query issue [duplicate]

This question already has an answer here:
Firebase query if child of child contains a value
(1 answer)
Closed 3 years ago.
I need a firebase query to filter the list based on the value of an array.
if any of the index of GID(Array) contains the given key. e.g my key is YsGMyfLSGRNHxDWQmhpuPRqtxlq1 and one node's GID have that on 0th index and other have that on 1st index. So these two lists need to be returned.
Currently, I can only get the one at 0th index using the code
//userID = YsGMyfLSGRNHxDWQmhpuPRqtxlq1
firebaseDatabase.child("Groups").queryOrdered(byChild: "GID/0").queryEqual(toValue:userID)
When I try to combine the query I am getting errors.
I don't know about your database structure, But I can explain that There is a limitation in Firebase Realtime database that you can only order by 1 child.
So now if we require to order by 2 Childs we can combine 2 nodes and make it 1 node and can apply order by query on it. For example
If we have username & email fields we can make a new field username_email and can apply order by on it.
Like
user: {
username: "john",
email: "john#g.com"
username_email = "john_john#g.com"
}
Now we can write
firebaseDatabase.child("user").queryOrdered(byChild: "username_email").queryEqual(toValue: "john_john#g.com");
There is no way you can filter your groups based on a value that exist within an array. If you want to query your database to get all groups a particular user is apart of, then you should consider augmenting your data structure to allow a reverse lookup. This means that you should add under each user object the groups in which that user is present.
This means that you'll need to duplicate some data, but this is not a problem when it comes to Firebase. This is a quite common practice, which is named denormalization and for that, I recommend you see this video, Denormalization is normal with the Firebase Database.
When you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.
However, what you need is actually allowed in Cloud Firestore. Its array-contains operator allow you to filter documents that have a certain value in an array. For more on this topic, please see the following post:
Better Arrays in Cloud Firestore.

Can Firebase return only some of the attributes? [duplicate]

Is there any way to select specific properties from firebase Realtime Database? I know there is a way to retrieve selected properties from firestore but how can get via Realtime database using Node.js
I want only Notes from everyone nothing else.
Suppose i just want to select Notes from Allergy here is my sample code which i tried but not successes...
admin.database().ref(`vitals/Allergy`).select('Notes').then(result => {//here is my result.....})
But it shows me that select is not a function.......
Realtime Database doesn't support "projections" like this (neither does Cloud Firestore). If you are going to query across multiple child nodes, you are going to get each entire child node that matches the query. Even if you want just one property of each child, you can't avoid the cost of downloading the entire child.
If your app is very sensitive to performance on these types of queries, consider duplicating the data such that there is another branch of your database that contains only the "Notes" property, and query that branch alone. This duplication is common in NoSQL type databases, and is call the "fan out" technique.
If you want to save download band then i can't help you further, otherelse:
let ArrayOfAllDownloadedNotes = [];
firebase.database().ref('yourRootFolders/vitals/Allergy').once((snapshot)=>{
ArrayOfAllDownloadedNotes = [...ArrayOfAllDownloadedNotes, snapshot.val().Notes];
});
//Reapeat the firebase formula for every child you want retrieve the Notes from
//You may also use forEach((item)=>{}) function for each folder you want to retrieve the //notes from if you want
console.log(My Array of Notes:',ArrayOfAllDownloadedNotes );

Categories

Resources