I am currently trying to write an app for an inventory management system and got a little stuck with one particular feature. I want to app to report to the user what stock is currently low in stock (upon request). I therefore added another field to be used in my product collection in firestore whereby the user can specify a minimum quantity on hand count. I want to know if it possible to obtain all the documents where (in my case) the current stock level is less than or equal to minimum stock level. In this case I have a single collection containing documents for each product, with each document containing various fields including the minquantity and currentquantity fields.
My only solution that I currently have is to obtain all the documents in the product collection and loop through every single one of them, but I am trying to improve the time it takes by minimizing the number of documents obtained.
There is no way to query Firestore in the way you want, you can't use a reference to a field in the value of a condition.
As usual when it comes to NoSQL databases, the solution is to add additional data to your data model to allow the use-case. In this case, consider adding a quantitityBeforeNeedToReorder field (there is probably a more concise name than that) and update that whenever you update the currentQuantityField too. With that field in place, your query is possible and quite simple.
You can even in security rules ensure that this quantitityBeforeNeedToReorder field has the correct value, as (unlike in queries) the security rules can do basic math between fields.
Related
As there is no functionality of foreign Key in Firestore like that of MYSQL, so I am not able to replicate one of my important functionality that is to update a file in one place and it will reflect in every place. Also, Firebase has no functionality to update all the document's specific filed at once.
There are already these kinds of questions but I could not get my solution. Suppose I have a million documents containing a filed which is the density of a material. Later on, I found that my density value was wrong so how to update that value in all documents efficiently. Also, I do not want to use server/admin SDK.
If you need to change the contents of 1 million documents, then you will need to query for those 1 million documents, iterate the results, then update each of those 1 million documents individually.
There is no equivalent of a sql "update where" statement that updates multiple documents in one query. It requires one update per document.
If don't want to use the Admin SDK, then the option that you have is to update the value of your densityMaterial property on the client, which might not be the best solution. However, if you can divide the update operation in smaller chunks, you might succeed.
If you are using a POJO class to map each document, then you might be interested in my answer from the following post:
How to update one field from all documents using POJO in Firestore?
And if you are not using a POJO class, please check my answer from the following post:
Firestore firebase Android search and update query
Regarding the cost, you'll be billed with one write operation for every document that is updated. If all 1 MIL documents will be updated, then you'll be billed with 1 MIL write operations.
Edit:
Suppose I have a million documents containing a filed which is the density of a material. Later on, I found that my density value was wrong so how to update that value in all documents efficiently.
If all of those 1 MIL documents contain a property called densityMaterial, that holds the exact same value, it doesn't make any sense to store that property within each document. You can create a single document that contains that particular value, and in each and every document of those 1 MIL, simply add only a reference to that document. A DocumentReference is a supported data-type. Now, if you need to change that value, it will incur only a single document write.
However, if you have different values for the densityMaterial property and all of them are wrong, then you don't have a problem with the database, you have a problem with the mechanism/people that are adding data. It's not a matter of a database problem if you have added 1 MIL incorrect documents.
Why not chose MySQL?
MySQL cannot scale in the way Cloud Firestore does. Firestore simply scales massively.
Can I avoid this problem anyhow?
Yes, you can buy using a single document for such details.
My idea is to create a like&unlike system for posts (a user can like and unlike a post) and to show a list of users in a fragment, ordered this way: the top user is the one for which there are the most numerous likes.
In my Firebase Firestore database:
I have a collection of posts. Each document (which is a post) contains the ID of the user that created it, and a counter of likes (I call it "A").
I have another collection, of users. Each document (which is a user) contains a counter (I call it "B") that counts for the number of likes, all posts combined.
For the moment, I use "B" to order the users in the list of users I've described above. I use "B" this way: return FirebaseFirestore.getInstance().collection("users").orderBy("likes", Query.Direction.DESCENDING);.
However, due to some technical facts in relation to Firebase Security Rules, and to simplify the database structure, I would want to only use "A", and remove "B". More precisely, I would want to get all the users, and order them according to "A". However, the counter "A" is defined in the documents of the collection of posts, whereas the counter "B" was defined in the documents of the collection of users: that makes it easier to use.
So my question is: for each user, I would have to get all their posts, then sum up their counter "A", then get all the users, then order them according to this sum. However, I would want to know: is it possible to do this using Firebase Firestore Android API? (something like the instruction given before) In others words: How to order documents from a collection, according to the field of documents of another collection? But note that in fact it's more difficult, since I must sum up the counter "A" of each post created by the user.
What you're trying to do is essentially a "join" type operation, which is not supported by Firestore. A Firestore query can only consider documents in a single collection at a time. If you have data from two collections to use for the purpose of generating query results, you will have at least two queries to perform.
The only real alternative you have is to introduce a third collection with data already merged from the other two collections that supports the query you want to make. This is common in NoSQL type databases, and is called "denormalization".
I have data structure like this:
Employees (Collection) > {EmployeeID} (Documents) > Chat (Collection) > {ChatId} (Documents).
In chat collection each document having 3 fields. 1. senderName, 2. sendTimestamp, 3. messageText.
I want to delete chats which are older than 7 days (from today).
I think it might be possible through cloud function but I am really basic user and don't know much about cloud functions. Please note that I don't want to make it automatically (cron job). I will do it manually on daily basis or whenever I wish.
I really searched a lot for this but its really hard. Please help me.
A big part of this task involves querying a sub collection. You can read more about this idea here: Firestore query subcollections
There are basically two options at the time of writing this:
Query the entire top level collection (Employees) something like db.collection('Employees').get(). Then you would have to loop through each employ object querying for their sub collection (Chat) based on their date range. Firestore query by date range for more reading on querying by a date in firestore. This could result in a large amount of reads depending on the number of Employee documents, but is the "easiest" approach in terms of not having to make changes to your data models/application.
Restructure your data to make the sub collection Chat a top level collection. Then you can do a query on this top level collection by the date. Less reads, but may not be as feasible depending on if this app is in production/willingness to make code changes.
A Function would definitely be able to accomplish this task either way you decide to approach it. One thing to note is that a Function executes using the Admin SDK, meaning it can basically ignore security rules set up on your Firestore.
I have a Firebase Firestore collection of products (125 and growing). Each product document has about 18 properties (name, price, stock etc). I can get all the documents successfully using:
val product = document.toObject(Product::class.java)
but I can use:
val name = document.getString("name")
Which is more recommended?
According to your actual structure where you have only 125 items, you can use each one you want. If your collection will grow so much as it will contain a very large number of documents, there might be a reasons why you should not use the first approach. Cloud Firestore uses reflection, so in case of very large number of documents, your app might become a little bit slower.
Further more, if you only need to display one or two properties, why to get them all? So if you only really need a subset of the fields, just use the second approach.
So even if we talk about a small data set (maybe it's not your case) but I have seen data that was not formated properly in a way the developer want.
While developing, I often find it more convenient to use the direct accessor methods of the Document class to get the fields from a document. During this time I'm still figuring out what precise fields and types each entity has.
If/once all documents have the same fields, and your data model is fairly stable, I'd recommend defining a Product class to model the fields from the document in Java/Kotlin code.
I am attempting to search for all users who are a part of a given club/organization. I would have both the clubsOrgsId and clubsOrgsName. In the list of users these two data points are in an object named by the clubsOrgsId in a list called clubsOrgs, as seen below. Is this possible to do with a Firebase query; I would rather not run the search locally.
This app is being written in Kotlin but an answer is appreciated regardless of programming language.
Your current data structure allows your to efficiently find the club orgs for a given user. It does not allow you to efficiently find the users for a given club org. If you want that, consider adding an inverted data structure to allow it:
CLUBORGS
$cluborgid
users
$uid: true
With this additional structure in place, the lookups are super easy.
Also see:
Firebase query if child of child contains a value
Firebase Query Double Nested
Many to Many relationship in Firebase