我正在尝试使用 Firestore 做三件事:
- 获取“contentType”字段为“basic”的文档,
- 获取在某个时间点之后创建的文档。 (示例中为凌晨 5 点。)
- 根据“喜欢”数量对文档进行排序。
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 子句不匹配。
我已经创建了一个包含内容的复合索引
contentType 升序日期降序响应。如降序
。
期望与结果
我希望文档按 like
计数排序,并且所有文档都是“基本”类型并在今天早上 5 点之后创建。
相反,仅应用前两个条件,完全忽略第三个条件。两种条件的不同组合起作用。这三个条件结合在一起是行不通的。
所以我的问题是,由于 Firebase 文档没有说明有两个以上的多个 orderby 和 where 组合,这是一个错误还是根本不可能的事情?
最佳答案
我找到了解决该问题的方法。
原始查询需要三个字段的复合索引。因此在 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
字符串。)
这个查询需要两个复合索引:
标签数组 response.like Descending
和 contentType Ascending response.like Descending
。
幸运的是,这就像一个魅力。
添加信息 原始查询检查某天凌晨 5 点后创建的文档的集合,对我来说,范围检查似乎是问题所在。
只要上面的 Date.getDatabaseKey()
方法在同一天的 5:00:00 到次日 4:59:59 之间生成一个键,这个新查询的效果基本一样。
关于iOS - Firestore 复合索引中索引的多个 orderBy 和 where 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54498407/