How to aggregate queries in firebase - firebase

when i used to work with Ms SQL server i used to create for example this query
Select Sum(Amount * Price) from table
Can this be done in GOOGLE FIRE BASE this is so important before i start a new project
Note there will be more queries like that
How can we run such queries and how complex it can be
I relay need to either choose fire base or use normal SQL server to work on the project
Thanks

Cloud Firestore does not support native aggregation queries. However, you can use client-side transactions or Cloud Functions to easily maintain aggregate information about your data.
Cloud Firestore provides powerful query functionality for specifying which documents you want to retrieve from a collection or collection group.
You can also chain multiple where() methods to create more specific queries (logical AND). However, to combine the equality operator (==) with a range or array-contains clause (<, <=, >, >=, or array-contains
Cloud Firestore does not support the following types of queries:
Queries with range filters on different fields, as described in the previous section.
Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
Queries with a != clause. In this case, you should split the query into a greater-than query and a less-than query. For example, although the query clause where("age", "!=", "30") is not supported, you can get the same result set by combining two queries, one with the clause where("age", "<", "30") and one with the clause where("age", ">", 30).

Related

How does "in" operator works in Firebase behind the scenes with the way firebase indexes are stored?

I was watching this Firebase video, and one stuff that wasn't clear to me is that the "||" or OR operator isn't supported especially with the way Firebase store indexes.
It was stated that you have to make separate queries and join it on the client side instead of on the firebase side.
Isn't the in operator essentially just a convenience method and acts like multiple OR statements?
https://firebase.blog/posts/2019/11/cloud-firestore-now-supports-in-queries
It is a well known feature of Firestore indexes which are good for range queries. With the indexes applied , for an inequality query, the backend would still have to scan every document in the collection in order to come up with results, and thus will affect the performance when the number of documents increases with time.
So, as per your question regarding the backend logical working of the “in” operator when used in a query and which is also mentioned in this thread on addition of IN queries not only address this performance issue but also supports up to 10 equality clauses on the same field with a logical OR".The arguments which are passed in the “In” operator query, are compared when searching a document.This will allow you to fetch documents with your filter criteria and thus result in function operation to take less time rather than goind one by one through each item.
For the example you could do:
// Get all documents in 'foo' where status is open or upcoming
db.collection('foo').where('status','in',['open','upcoming']).get()
I would also recommend you to check these following similar examples:
How to perform compound queries with logical OR
How to make queries on firestore
Firebase database operator working
Firestore IN operator working
Firestore Query limitation

Firestore Query crashes while using whereNotEqualTo and multiple orderBy [duplicate]

Let's say I have a collection of cars and I want to filter them by price range and by year range. I know that Firestore has strict limitations due performance reasons, so something like:
db.collection("products")
.where('price','>=', 70000)
.where('price','<=', 90000)
.where('year','>=', 2015)
.where('year','<=', 2018)
will throw an error:
Invalid query. All where filters with an inequality (<, <=, >, or >=) must be on the same field.
So is there any other way to perform this kind of query without local data managing? Maybe some kind of indexing or tricky data organization?
The error message and documentation are quite explicit on this: a Firestore query can only perform range filtering on a single field. Since you're trying to filter ranges on both price and year, that is not possible in a single Firestore query.
There are two common ways around this:
Perform filtering on one field in the query, and on the other field in your client-side code.
Combine the values of the two range into a single field in some way that allows your use-case with a single field. This is incredibly non-trivial, and the only successful example of such a combination that I know of is using geohashes to filter on latitude and longitude.
Given the difference in effort between these two, I'd recommend picking the first option.
A third option is to model your data differently, as to make it easier to implement your use-case. The most direct implementation of this would be to put all products from 2015-2018 into a single collection. Then you could query that collection with db.collection("products-2015-2018").where('price','>=', 70000).where('price','<=', 90000).
A more general alternative would be to store the products in a collection for each year, and then perform 4 queries to get the results you're looking for: one of each collection products-2015, products-2016, products-2017, and products-2018.
I recommend reading the document on compound queries and their limitations, and watching the video on Cloud Firestore queries.
You can't do multiple range queries as there are limitations mentioned here, but with a little cost to the UI, you can still achieve by indexing the year like this.
db.collection("products")
.where('price','>=', 70000)
.where('price','<=', 90000)
.where('yearCategory','IN', ['new', 'old'])
Of course, new and old go out of date, so you can group the years into yearCategory like yr-2014-2017, yr-2017-2020 so on. The in can only take 10 elements per query so this may give you an idea of how wide of a range to index the years.
You can write to yearCategory during insert or, if you have a large range such as a number of likes, then you'd want another process that polls these data and updates the category.
In Flutter You can do something like this,
final _queryList = await db.collection("products").where('price','>=', 70000).get();
final _docL1 = _querList.where('price','<=', 90000);
Add more queries as you want, but for firestore, you can only request a limited number of queries, and get the data. After that you can filter out according to your need.

Flutter Firebase Query Filter Date Range overlapping with another Date Range [duplicate]

I have documents with a startDate and endDate. I would like to query between the range of the startDate and endDate. I can query between a range for one date like so:
whereField("startDate", isGreaterThan: start).whereField("startDate, isLessThan: end)
But I cannot query two fields like so:
whereField("startDate", isGreaterThan: start).whereField("endDate", isLessThan: end)
Firestore throughs an exception when using more than one field in a compound where statement.
No matter what is the platform that you are using for building your application, I'm sure that the error that you get is quite explicit. Cloud Firestore official documentation is also quite explicit regarding this topic. So there are some query limitations, when it comes to Firestore:
Cloud Firestore does not support the following types of queries:
Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
So a Firestore query can perform a range filtering only on a single property. Since you are trying to filter ranges on two properties, you're geeting that error message and this is the expected behaviour since this is not possible in a single Firestore query.
To solve this, you can choose from one of the following solutions:
You can perform filtering on one (first) field in the query and on the other (second) field client-side, as also the official documentation indicates.
You can combine the values of the two range into a single field in some way that allows your use-case with a single field. A very successful example of such a combination would be the use of geohashes for filtering on latitude and longitude properties as Frank van Puffelen explained very well in this video, Querying Firebase and Firestore.
Another option is to change the way your are storing your data and model it differently. The most simple implementation would be to put all items within the startDate and endDate into a single collection. Since you didn't choose a tag for a platform, I will write the necessary query in Javascript but it can be simply written also for other programming languages. So you can query that collection with the following query:
db.collection("startDate-endDate").where('date','>=', start).where('date','<=', end);
Another even more general alternative would be to store all your items in a collection for each periode you need (year, monts or days) separately, and then perform the necessary number of queries to get the items you are looking for one of each collection, itemsFromFirstYear, itemsFromSecondYear and so on.
Please take also take a look at the official documentation regarding:
document on compound queries and their limitations
video on Cloud Firestore queries.
IMHO, I'd recommend picking up the first option.

Cloud Firestore query/filter with bitwise operators

I want to query all documents on my Cloud Firestore database which have an identifier that returns true when performing certain bitwise operations on it. I have looked into structured query operators but bitwise operators do not seem to be supported.
The filtering should be performed on the server side.
Am I missing out on something? Is there any way I can use bitwise operators for my queries? If not are there any alternative solutions?
Firestore requires you to query against the actual values of fields stored in documents, as only those values are present in the indexes that Firestore creates. It would not be scalable to scan an entire collection, performing any sort of transformation (bitwise or otherwise) to come up with matching documents. In fact, Firestore does not allow any queries that can't be serviced by an efficient index lookup of document fields.
You could try to precompute the expected transformations and store the results of those for querying. But if you want very flexible querying based on values that are not known ahead of time, Firestore isn't the right tool for the job.

Between StartDate and EndDate Firestore

I have documents with a startDate and endDate. I would like to query between the range of the startDate and endDate. I can query between a range for one date like so:
whereField("startDate", isGreaterThan: start).whereField("startDate, isLessThan: end)
But I cannot query two fields like so:
whereField("startDate", isGreaterThan: start).whereField("endDate", isLessThan: end)
Firestore throughs an exception when using more than one field in a compound where statement.
No matter what is the platform that you are using for building your application, I'm sure that the error that you get is quite explicit. Cloud Firestore official documentation is also quite explicit regarding this topic. So there are some query limitations, when it comes to Firestore:
Cloud Firestore does not support the following types of queries:
Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
So a Firestore query can perform a range filtering only on a single property. Since you are trying to filter ranges on two properties, you're geeting that error message and this is the expected behaviour since this is not possible in a single Firestore query.
To solve this, you can choose from one of the following solutions:
You can perform filtering on one (first) field in the query and on the other (second) field client-side, as also the official documentation indicates.
You can combine the values of the two range into a single field in some way that allows your use-case with a single field. A very successful example of such a combination would be the use of geohashes for filtering on latitude and longitude properties as Frank van Puffelen explained very well in this video, Querying Firebase and Firestore.
Another option is to change the way your are storing your data and model it differently. The most simple implementation would be to put all items within the startDate and endDate into a single collection. Since you didn't choose a tag for a platform, I will write the necessary query in Javascript but it can be simply written also for other programming languages. So you can query that collection with the following query:
db.collection("startDate-endDate").where('date','>=', start).where('date','<=', end);
Another even more general alternative would be to store all your items in a collection for each periode you need (year, monts or days) separately, and then perform the necessary number of queries to get the items you are looking for one of each collection, itemsFromFirstYear, itemsFromSecondYear and so on.
Please take also take a look at the official documentation regarding:
document on compound queries and their limitations
video on Cloud Firestore queries.
IMHO, I'd recommend picking up the first option.

Resources