I'm trying to do three things using Firestore:
- fetch documents whose "contentType" field is "basic",
- fetch documents that are created past a certain point in time. (5AM in the example.)
- order documents according to the "like" count.
The documents in the contents
collection look like this (leaving out unnecessary details):
{
date: Timestamp;
contentType: string;
response: {
like: Number;
};
}
And here is the iOS code:
let dateKey = "date"
let likeKey = "response.like"
let startDate = Date().setLocalHour(5)
let timestamp = Timestamp(date: startDate)
Firestore.firestore()
.collection(path: .contents)
.whereField(.contentType, isEqualTo: "basic")
.whereField(dateKey, isGreaterThanOrEqualTo: timestamp)
.order(by: dateKey, descending: true)
.order(by: likeKey, descending: true)
.limit(to: Constant.fetchLimit)
The order(by: dateKey)
part is only necessary because Firebase demands it. Otherwise, an exception will be thrown, complaining that the where clause and the orderby clauses don't match.
I already created a composite index that says contents
contentType Ascending date Descending response.like Descending
.
Expectation & Results
I'm expecting the documents to be ordered by the like
count, and all documents to be "basic" type and created past 5 a.m. of today.
Instead, only the first two conditions are applied, and the third is completely ignored. Different mixes of two conditions work. It's the three conditions combined that is not working.
So my questions is, since Firebase documents don't say anything about having more than two multiple orderby & where combinations, is this a bug or something that's just not possible?
I found a workaround to the problem.
The original query required a composite index of three fields. So there is only one range comparison on
date
--contentType
is used only for equality check--and two ordering ondate
andresponse.like
, both of which compose the composite index.Instead I decided to add a field in the
contents
document like so:And the new query looks like this:
(
Date.getDatabaseKey()
just creates ayyyy-MM-dd
string based on the current date.)This query requires two composite indexes:
tags Arrays response.like Descending
andcontentType Ascending response.like Descending
.Fortunately, this works like a charm.
Added Info The original query checked the collection for documents created after 5 AM of a certain day, and to me the range check seemed to be the problem.
As long as the
Date.getDatabaseKey()
method above generates a key with the same day for hours 5:00:00 to 4:59:59 of the next day, this new query has basically the same effect.