11

I have been trying to figure out a way to query a list of documents where I have a range filter on one field and order by another field which of course isn't possible, see my other question: Order by timestamp with range filter on different field Swift Firestore

But is it possible to save documents with the timestamp as id and then it would sort by default? Or maybe hardcode an ID, then retrieve the last created document id and increase id by one for the next post to be uploaded?

This shows how the documents is ordered in the collection

This shows how the documents is ordered in the collection

Any ideas how to store documents so they are ordered by created at in the collection?

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
user3116871
  • 313
  • 2
  • 5
  • 18

4 Answers4

19

It will order by document ID (ascending) by default in Swift.

You can use .order(by: '__id__') but the better/documented way is with FieldPath documentID() I don't really know Swift but I assume that it's something like...

.order(by: FirebaseFirestore.FieldPath.documentID())

JavaScript too has an internal variable which simply returns __id__.

.orderBy(firebase.firestore.FieldPath.documentId())

Interestingly enough __name__ also works, but that sorts the whole path, including the collection name (and also the id of course).

Ryan Taylor
  • 12,559
  • 2
  • 39
  • 34
  • .order(by: '__name__') this has syntax errors, please check your answer before posting as it wastes our time ;) –  Dec 30 '19 at 23:18
  • updated to make it do `order(by: '__id__')`, but no the underscores are intentional, otherwise it would refer to a field named "id" or "name" and not the document id (or full path, in the case of `__name__`) – Ryan Taylor Jan 02 '20 at 17:04
  • I think this does the same: .orderBy(firebase.firestore.FieldPath.documentId()) –  Jan 04 '20 at 10:52
  • 1
    @bmm nice find!! that's a better more idiomatic solution, and it's even documented aha – Ryan Taylor Jan 07 '20 at 21:00
0

If I correctly understood your need, by doing the following you should get the correct order:

For each document, add a specific field of type number, called for example sortNbr and assign as value a timestamp you calculate (e.g. the epoch time, see Get Unix Epoch Time in Swift)

Then build a query sorted on this field value, like:

let docRef = db.collection("xxxx")
docRef.order(by: "sortNbr")

See the doc here: https://firebase.google.com/docs/firestore/query-data/order-limit-data

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
0

Yes, you can do this.

By default, a query retrieves all documents that satisfy the query in ascending order by document ID.

See the docs here: https://firebase.google.com/docs/firestore/query-data/order-limit-data

So if you find a way to use a timestamp or other primary key value where the ascending lexicographical ordering is what you want, you can filter by any fields and still have the results sorted by the primary key, ascending.

Be careful to zero-pad your numbers to the maximum precision if using a numeric key like seconds since epoch or an integer sequence. 10 is lexicographical less than 2, but 10 is greater than 02.

Using ISO formatted YYYY-mm-ddTHH:MM:SS date-time strings would work, because they sort naturally in ascending order.

Eloff
  • 20,828
  • 17
  • 83
  • 112
  • Why would you do this when you can simply store a proper timestamp value as a field, and sort on that field? Depending on this default behavior doesn't seem to make sense in this case. – Doug Stevenson Oct 18 '18 at 04:31
  • 1
    The OP posted a question where it isn't possible to filter on one field and sort on another. But I wonder if that's not outdated now? IIRC I've done this using compound indices, at least through the web API. – Eloff Oct 19 '18 at 18:13
-2

The order of the documents shown in the Firebase console is mostly irrelevant to the functioning of your code that uses Firestore. The console is just for browsing data, and that sorting scheme makes it relatively intuitive to find a document you might be looking for, if you know its ID. You can't change this sort order in the console.

Your code is obviously going to have other requirements, and those requirements should be coded into your queries, without regarding any sort order you see in the dashboard. If you want time-based ordering of your documents, you'll have to store some sort of timestamp field in the document, and use that for ordering. I don't recommend using the timestamp as the ID of a document, as that could cause problems for you in the future.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Have you followed the link above? It explains that it's not possible to create a query where I create a range filter on one field and order by another. – user3116871 Apr 24 '18 at 21:52
  • When I fetched the data into my application using getDocuments, they are ordered in the same way as in the console on firestore. is this just a coincidence? – user3116871 Apr 24 '18 at 21:55
  • If you need a sort order for your documents, you should specify one in your query. The documentation doesn't define the sort order if you don't, so you shouldn't depend on incidental behavior. – Doug Stevenson Apr 24 '18 at 21:57
  • You just shattered a dream of an easy solution haha, but that did answer my question, thanks. – user3116871 Apr 24 '18 at 22:19
  • 2
    @DougStevenson it's not incidental behavior: "By default, a query retrieves all documents that satisfy the query in ascending order by document ID." – Eloff Oct 18 '18 at 01:02