SNM
SNM

Reputation: 6785

Firestore not ordering my results depending on timestamp

I'm trying to get all my posts which time is newer ones first, I have made this query that should bring to me all the newest posts that I uploaded or other people did.

Thing is that I'm getting posts shuffled with timestamps , there are all mixed up instead of ordered by new ones

If I do the same query from the firebase console they are ordered the way it should

My recyclerview does NOT have any reverselayout or stackfromend attributes and I'm not expecting to use them, instead I just want my list to come from firebase ordered

@ExperimentalCoroutinesApi
    suspend fun getLatestPosts(): Flow<Result<List<Post>>> = callbackFlow {

        val postList = mutableListOf<Post>()

        // Reference to use in Firestore
        var eventsCollection: CollectionReference? = null
        try {
            eventsCollection = firestore.collection("posts")
            eventsCollection.orderBy("created_at", Query.Direction.DESCENDING)
        } catch (e: Throwable) {
            // If Firebase cannot be initialized, close the stream of data
            // flow consumers will stop collecting and the coroutine will resume
            close(e)
        }

        val suscription = eventsCollection?.addSnapshotListener { value, error ->
            if (value == null) {
                return@addSnapshotListener
            }

            try {
                postList.clear()
                for (post in value.documents) {
                    post.toObject(Post::class.java)?.let { fbPost ->
                        fbPost.apply {
                            created_at = post.getTimestamp(
                                "created_at",
                                DocumentSnapshot.ServerTimestampBehavior.ESTIMATE
                            )?.toDate()
                        }
                        postList.add(fbPost)
                    }
                }
                offer(Result.Success(postList))
            } catch (e: Exception) {
                close(e)
            }
        }

        awaitClose { suscription?.remove() }
    }

Now if I sort the list locally after getting the data that works, but I don't want it to be client side, I want to have an ordered list from the server.

What I'm doing wrong ?

Posts timestamp are saved with @ServerTimestamp and Date format into Firestore

Upvotes: 0

Views: 37

Answers (2)

Doug Stevenson
Doug Stevenson

Reputation: 317392

CollectionReference (Query) objects are immutable - they can't be changed once created. They use a builder type pattern to construct new Query objects by adding constraints. The original Query remains unmodified.

If you want to compose a set of operations to perform on a Query, you would have to remember the new Query returned by each operation. An easy way to do this is by reassigning the prior Query if you no longer need it:

var eventsQuery: Query = firestore.collection("posts")
eventsQuery = eventsQuery.orderBy("created_at", Query.Direction.DESCENDING)

Or you can do it as a chained sequence of operations, which is more idiomatic in the case that you know all the operations ahead of time:

val eventsQuery = firestore
    .collection("posts")
    .orderBy("created_at", Query.Direction.DESCENDING)

If you need to conditionally apply operations, however, you will need to take the first approach. A more detailed explanation can be found here: Firestore: Multiple conditional where clauses

Upvotes: 1

SNM
SNM

Reputation: 6785

Problem was at this line

eventsCollection = firestore.collection("posts")
eventsCollection.orderBy("created_at", Query.Direction.DESCENDING)

Seems like I need to wrap it up all into 1 line and make it a Query, it does not apply any changes to the eventsCollection, this can be done changing CollectionReference to Query

Upvotes: 1

Related Questions