3

I have a subcollection with the path of /coll_A/document_A/coll_B, where coll_A/_B - are collections. I want to query this subcollection with ordering and limit:

firestore.collection("coll_A")
        .document("document_A")
        .collection("coll_B")
        .orderBy("time", DESCENDING)
        .limit(10)
        .get()
        .addOnCompleteListener(...)

But it always returns the full collection. What am I doing wrong?

time is a number timestamp.

Upd.: time is just an example, I used an integer field before. As per answer from Alex Mamo, it should be able to order by it.

Upd. 2 I tried to prepare a screenshot and removed and re-added the data - and it started to work. Data is all the same, collection-doc-collection hierarchy also, so probably some kind of a glitch.

khusrav
  • 5,267
  • 5
  • 27
  • 38

1 Answers1

2

To solve this, your date should be stored as a Date object as explained here and not as a number as you say. So to solve this, please change your query to:

firestore.collection("coll_A")
    .document("document_A")
    .collection("coll_B")
    .orderBy("date", Query.Direction.DESCENDING)
    .limit(10)
    .get()
    .addOnCompleteListener(...)

As per Firestore Supported Data Types documentation, you can sort your records chronological by date and time. Saving the date and time as a ServerValue.TIMESTAMP was useful when using Firebase Realtime database. In the new Cloud Firestore, you need to store the date as a Date object in order to be able to sort your records according to it. Please see also here informations about ServerTimestamp:

Annotation used to mark a timestamp field to be populated with a server timestamp. If a POJO being written contains null for a @ServerTimestamp-annotated field, it will be replaced with a server-generated timestamp.

So this is the correct way in which you can achieve what you want.

If you are interested, this is how you can update a Date in case you need it.

Edit:

You can order by integers or strings but keep in mind this: When ordering by strings remember that strings are ordered lexicographically while ordering by date you'll get a chronological order.

The object that results from setting a Cloud Firestore field with FieldValue.serverTimestamp() is an instance of java.util.Date. When you later read the value, you can get the epoch time using getTime(). This is why Firebase team added this new supported data type, which is more useful then the regular data stored as a number.

If you want to improve your query with more limitation you can use also whereEqualTo(), whereGreaterThan(), whereGreaterThanOrEqualTo(), whereLessThan() or whereLessThanOrEqualTo().

As a conclusion, the best way to store a date is to store it a Date object.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • But I don't want a date, it should be orderable and limitable by a number – khusrav May 30 '18 at 06:46
  • I still don't follow - I can't order and limit by an integer, string, etc? – khusrav May 30 '18 at 08:12
  • Thanks for the update, the problem is it doesn't work. I know and expect the lexicographically sorting of strings, and I expect the ints to be sorted out of the box. The time in the post is also just a number, it should be sortable/limittable – khusrav May 30 '18 at 08:41
  • Please add a screenshot of your database structure. Is there any other limitation that you are using in your query other than `orderBy` and `limit`? – Alex Mamo May 30 '18 at 08:43
  • please see my update - it suddenly started working, I think I should accept your answer as gives good answer on how the ordering should be. – khusrav May 30 '18 at 09:40