Sorting firestore collection before and after limiting - firebase

I am trying to get the last 1000 items from firestore and then sort them in ascending. So I tried
connection()
.collection(`somecollection`)
.orderBy("timestamp", "desc")
.limit(1000)
.orderBy("timestamp")
Having orderBy twice doesn't seem to work. But works with one orderBy
I know I could do this in client but is it possible to run this am I missing something here.

You don't even need to orderBy by ascending, as it is by default.
connection()
.collection(`somecollection`)
.limit(1000)
EDIT:
Firestore doesn't support the functionality you are looking for, so you need to query the initial data in a descending order, and the on client sort it in the way you need
connection()
.collection('somecollection')
.orderBy('timestamp', 'desc')
.limit(1000);

Related

Using multiple array-contains in firestore

In the following code, I want to use multiple array-contains queries, which is inappropriate according to firebase limitations.
await firestore
.collection("collection")
.where("field1", "array-contains", value1)
.where("field2", "array-contains", value2)
.where("field3", "array-contains", value3)
.get();
Tried to find a workaround solution by adding all values to one array and query on that array but it seems firebase does not support array-contains-all query.
Any suggestion how can I reframe my query?

How to use whereIn filter multiple times in a query

I am using this code to retrive data from firestore
querysnap = FirebaseFirestore.instance
.collection("datas")
.where("cat", whereIn: Cateogryarray )
.where("City", whereIn:Cityarray)
.snapshots();
Then I get this error.
You cannot use 'whereIn' filters more than once.
How can I execute this query.
As the Firestore documentation on query limitations says:
You can use at most one in, not-in, or array-contains-any clause per query. You can't combine these operators in the same query.
Since you're trying to use two in clauses in your query, Firestore gives an error.
The most common workaround is to run with one clause against the database (typically the one you expect to exclude most documents from the result), and perform the rest of the filtering in your application code.
Another idea is to get individual snapshots for each parameter that would need the inclause.
Then once you have each of your snapshots, do an intersection of the lists. This will return the results where every record adheres to each individual filter.

Paginate data with offset on an non order firestore query

If I use offset and limit to paginate query, do I need to specify an order?
In other words, a query with no order specified, uses some implicit order, like key order?
In a SQL database, if I don't specify an order, SQL engine will return the results in the order he pleases. So the second time the query is run, the results may be staked in a different order, so offset and limit would not cut the result as wanted.
Making the assumption you want to order your documents by creation date, in Firestore this would need an extra field, as explained in the Firestore documentation (link):
Unlike "push IDs" in the Firebase Realtime Database, Cloud Firestore
auto-generated IDs do not provide any automatic ordering. If you want
to be able to order your documents by creation date, you should store
a timestamp as a field in the documents.

orderBy date but have nulls last

I'm querying firestore with:
this.todosCollection = this.afs.collection('todos', ref => ref.where('owner', '==', this.userId). orderBy('due', 'asc'));
The todo items is ordered in ascending order as I want, the problem is that todos without a due date (null) comes first. I want them to come last. Is this possible within the orderBy or other technique?
That's the way the ordering of nulls is intended to work. The documentation makes this clear, and it can't be changed in the query itself.
If you want to change the ordering, then you will have to manually re-sort the documents on the client to support your preferred ordering. Or, you will have to make two queries, one that includes null and another that does not, then merge the results yourself.

Possible linq bug/issue

I was having an issue with a LINQ query today and after some debugging I was able to resolve the issue but it seems like a bug to me in the way LINQ works. Here is what I had:
var myitem = context
.items
.OrderByDescending(x => x.DateEdited)
.FirstOrDefault(x => x.fkId == myFkId && x.DateEdited < someDate);
In my database I have a table with some records and I want to retrieve the most recent record that is older than "someDate" and who has a particular foreign key in a column. The above query did not work however. It was returning the oldest record with the matching foreign key. I ended up having to rewrite my query like this to get it to work:
var myitem = context
.items
.Where(x => x.fkId == myFkId && x.DateEdited < someDate)
.OrderByDescending(x => x.DateEdited)
.FirstOrDefault();
In my debugging I found out that the "x.DateEdited < someDate" was re-ordering the IEnumerable so I ended up having to put my OrderByDescending clause after the date check.
Has anybody else run into this issue? Is it a bug or expected functionality?
Even though .OrderByDescending() returns an IOrderedEnumerable, the .FirstOrDefault() is a shortcut to .Where() which only returns an IEnumerable which does not guarantee order.
Basically, adding a filter does not guarantee the order of the data. If you look at the generated SQL from the first, you will get a nested subresult from the orderby that is then filtered again.
Generally, if an operation does not explicitly define the output order, you can't depend on the result being in any particular order until you specify/apply it yourself.
Unless you know that ordering an intermediate result will yield performance improvements in the next step of an algorithm, there's no reason to so. Just apply the ordering as a final processing step.

Resources