我正在尝试使用Firestore做三件事:
contents
集合中的文档如下所示(省略了不必要的细节):
{
date: Timestamp;
contentType: string;
response: {
like: Number;
};
}
这是iOS代码:
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)
order(by: dateKey)
部分仅是必需的,因为Firebase需要它。否则,将引发异常,并抱怨where子句和orderby子句不匹配。
我已经创建了一个复合索引,内容为contents
contentType Ascending date Descending response.like Descending
。
期望与结果
我希望文档按like
的顺序进行排序,并且所有文档都是“基本”类型,并在今天凌晨5点以后创建。
相反,仅应用了前两个条件,而第三个条件被完全忽略。两个条件的不同组合起作用。这是三个条件组合不起作用。
所以我的问题是,由于Firebase文档没有说两个以上的orderby和何处组合,这是bug还是根本不可能?
答案 0 :(得分:1)
我找到了解决该问题的方法。
原始查询需要三个字段的复合索引。因此,date
上只有一个范围比较 – contentType
仅用于相等性检查-date
和response.like
上只有两个排序,两者都组成了复合索引。
相反,我决定像这样在contents
文档中添加一个字段:
{
tags: string[]; // the new field.
date: Timestamp;
contentType: string;
response: {
like: Number;
};
}
新查询如下:
Firestore.firestore()
.collection(path: .contents)
.whereField(.tags, arrayContains: Date.getDatabaseKey())
.whereField(.contentType, isEqualTo: "basic")
.order(by: likeKey, descending: true)
.limit(to: Constant.fetchLimit)
({Date.getDatabaseKey()
仅根据当前日期创建一个yyyy-MM-dd
字符串。)
此查询需要两个复合索引:
tags Arrays response.like Descending
和contentType Ascending response.like Descending
。
幸运的是,这就像一个护身符。
添加的信息 原始查询检查集合中是否有某天凌晨5点之后创建的文档,对我而言,范围检查似乎是问题所在。
只要上面的Date.getDatabaseKey()
方法在第二天的5:00:00到第二天的 4:59:59的同一天生成密钥,效果基本相同。