如何用resultsLimit严格限制CloudKit结果的数量

How to strictly limit the number of CloudKit results with resultsLimit

提问人:Stan 提问时间:11/17/2023 更新时间:11/17/2023 访问量:23

问:

我给你设置一个场景:我有一个 CloudKit 数据库,里面有 1000 条记录。我需要拿 150。

问题 #1:默认情况下,CloudKit 返回 100 条记录和一个游标。如果我使用该游标获取下一批,我最终将获取 200 条记录。即使这样也不能保证,这使我们,

问题 #2:100 条记录数不是固定的。CloudKit 将根据 CloudKit 服务器的当前负载来决定返回多少条记录。因此,例如,在第一个查询中只能获得 30 条记录,在第二个查询中只能获得 30 条记录 = 60。

问题 #3:如果我在循环中获取下一批,我最终会得到所有 1000 条记录。

这是我的循环代码,只是为了测试,我设置了一个.resultsLimit: 75

func fetchRecords() async throws -> [CKRecord] {
        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "MyRecordType", predicate: predicate)
        query.sortDescriptors = [NSSortDescriptor(key: "datePublished", ascending: false)]
        
        var records: [CKRecord] = []
        var (matchResults, queryCursor) = try await CKContainer(identifier: "iCloud.MyDB").publicCloudDatabase.records(matching: query, resultsLimit: 75)
        
        records.append(contentsOf: matchResults
                                    .compactMap { _, result in try? result.get()}
                                    .compactMap { $0 })

        while let cursor = queryCursor {
            (matchResults, queryCursor) = try await CKContainer(identifier: "iCloud.MyDB").publicCloudDatabase.records(continuingMatchFrom: cursor, resultsLimit: 75)
            records.append(contentsOf: matchResults
                                        .compactMap { _, result in try? result.get()}
                                        .compactMap { $0 })
        }
        
        print("Will return \(records.count) CloudKit records")
        return records
    }

此方法将返回所有 1000 条记录,按 75 / 查询获取它们。

有没有办法严格要求 CloudKit 交付 150 条记录(无论是否批量,但不超过 150 条),或者我应该低效地使用数据库并从 CloudKit 中获取尽可能多的记录(比如 200 条),然后用 Swift 代码手动选择其中的 150 条?

Swift CloudKit 云套件

评论


答:

2赞 HangarRash 11/17/2023 #1

这是 CloudKit 将返回的最大行数。而不是硬编码为循环。根据您还需要获得多少个结果来调整该数字。一旦你达到预期的目标,就打破循环。resultsLimit75resultsLimitwhilewhile

假设有一个名为 150 或任何其他所需行数的变量。maxRows

while let cursor = queryCursor && records.count < maxRows {
    let limit = maxRows - results.count
    (matchResults, queryCursor) = try await CKContainer(identifier: "iCloud.MyDB").publicCloudDatabase.records(continuingMatchFrom: cursor, resultsLimit: limit)
    records.append(contentsOf: matchResults
                                .compactMap { _, result in try? result.get()}
                                .compactMap { $0 })
}