iOS-Firestore复合索引中索引的多个orderBy和where子句

时间:2019-02-02 23:10:26

标签: ios swift firebase google-cloud-firestore

我正在尝试使用Firestore做三件事:

  • 获取“ contentType”字段为“基本”的文档,
  • 获取在特定时间点之后创建的文档。 (在示例中为5AM。)
  • 根据“喜欢”计数排序文档。

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还是根本不可能?

1 个答案:

答案 0 :(得分:1)

我找到了解决该问题的方法。

原始查询需要三个字段的复合索引。因此,date上只有一个范围比较contentType仅用于相等性检查-dateresponse.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 DescendingcontentType Ascending response.like Descending

幸运的是,这就像一个护身符。

添加的信息 原始查询检查集合中是否有某天凌晨5点之后创建的文档,对我而言,范围检查似乎是问题所在。

只要上面的Date.getDatabaseKey()方法在第二天的5:00:00到第二天的 4:59:59的同一天生成密钥,效果基本相同。