【问题标题】:Firestore order and limit data returns missing resultsFirestore 订单和限制数据返回缺失的结果
【发布时间】:2020-07-04 05:13:19
【问题描述】:

当我在 Firestore 中获取用户记录时,我想做一些事情:

  • 筛选年龄范围内的用户
  • 根据性别、位置过滤用户
  • 获取最近 6 个最近加入的用户
  • 获取今天之前创建的用户
func observeUsers(){
let location = "Paris"
let gender = "male"
let startAge = 15
let endAge = 30
let today: Double = Date().timeIntervalSince1970

var query = db.collection("users") as Query

query
.whereField("location", isEqualTo: location)
.whereField("age", isGreaterThanOrEqualTo: startAge)
.whereField("age", isLessThanOrEqualTo: endAge)
.order(by: "age", descending: true) 
.order(by: "created", descending: true)
.start(at: [today])
.limit(to: 6)
.getDocuments { (querySnapshot, error) in
            if let err = error {
                print(err.localizedDescription)
                return
            }
            guard let docs = querySnapshot?.documents else {
                return
            }
            docs.forEach({ (doc) in
                print(doc.data())
            })
}
}

我只启用了一个复合索引location Ascending gender Ascending age Descending created Descending

每个用户都有相同的字段:["gender": male, "created": 1585606054.78943, "firstname": Seven, "location": Paris, "age": 22 ]

当查询限制为 12 时,返回所有用户:Seven, Brian, Aaron, Chuck, Sally, Marty, Jessie, Trevor, Riley, Boren, Michael, France

当查询限制为 6 时,按此顺序返回以下用户: Chuck, Sally, Marty, Jessie, Riley, Boren

预期:Seven, Brian, Aaron, Chuck, Sally, Marty前六个用户被退回

是反向分页或索引的问题吗?是因为我按两个字段排序数据吗?查询游标是否不够唯一?

非常感谢您的帮助!

【问题讨论】:

  • 您是否尝试过使用纯 javascript 来查看会发生什么?
  • @Jonathan 你是说firebase的云功能吗?我没有深入探索,但是更改语言应该不会影响查询或返回的数据?
  • Swift 界面中可能存在错误。但是,看起来您更改了 Start() 函数和 limit() 函数,这肯定会改变您的结果。
  • 什么是.start(at: [today]) .... [今天]?您是否尝试将其打印出来以查看该属性包含的内容?
  • @Jay 今天是我分配给 let today: Double = Date().timeIntervalSince1970 的 Double。即使我不包含.start(at: [today]) 并且只限制结果,数据也没有正确返回,不知道为什么

标签: swift firebase google-cloud-firestore pagination


【解决方案1】:

在问题中,fruits 数组为空,这实际上会导致查询崩溃。所以我更新了代码,将一些水果添加到该数组中,每个用户集合中都有一个水果,这样它们就可以匹配查询。

我在 Firestore 中使用您的确切数据填充了 COLLECTION_USERS 集合 - 一个例外是文档 ID 为 uid_0、uid_1、uid_2,但字段完全匹配。

然后我运行更新后的代码,它返回所有三个用户。

这是更新后的代码,除了这几个更改之外,它是相同的。 (我也在今天的变量中添加了 cmets 中提到的)

func querySomeData() {
    var fruits: [String] = []
    let location = "New York"
    let gender = "male"
    let startAge = 20
    let endAge = 30
    let today: Double = Date().timeIntervalSince1970

    fruits.append(contentsOf: ["ea", "et", "id"])

    let collectionUsers = self.db.collection("COLLECTION_USERS")
    collectionUsers
        .whereField("favoriteFruits", arrayContainsAny: fruits)
        .whereField("location", isEqualTo: location)
        .whereField("gender", isEqualTo: gender)
        .whereField("age", isGreaterThanOrEqualTo: startAge)
        .whereField("age", isLessThanOrEqualTo: endAge)
        .order(by: "age", descending: true) // or ascending
        .order(by: "created", descending: true)
        .start(at: [today])
        .limit(to: 6)
        .getDocuments() { querySnapshot, error in

            if let err = error {
                print(err.localizedDescription)
                return
            }

            guard let docs = querySnapshot?.documents else { return }

            for doc in docs {
                print(doc.documentID)
            }

    }
}

和输出

uid_0
uid_2
uid_1

因此,除非存在这两个差异(向数组和 documentID 添加水果),问题中的代码才有效。

编辑:

OP 还希望返回没有最喜欢水果的用户,因此 Firestore 中的数组将为空。您不能查询空数组,因为“arrayContainsAny”过滤器需要非空数组。所以简单的解决方案是添加一个占位符(在 NoSQL 数据库中很常见),指示用户没有最喜欢的水果。所以 Firestore 中的数组看起来像这样:

favoriteFruits
   0: "none"

查询会包含这个

fruits.append(contentsOf: ["ea", "et", "id", "none"])

这将返回所有拥有那些最喜欢的水果或没有最喜欢的水果的用户。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
相关资源
最近更新 更多