CKError:查询过滤器超出了值的限制:容器为 250

Posted

技术标签:

【中文标题】CKError:查询过滤器超出了值的限制:容器为 250【英文标题】:CKError: Query filter exceeds the limit of values: 250 for container 【发布时间】:2017-07-27 09:26:51 【问题描述】:

我想从公共数据库中提取大约 500 条“访问”记录。 CloudKit 一次只给你 100 条记录,所以我只使用下面的 CKQueryCursor 来获取我想要的所有记录。

func fetchVisits(_ cursor: CKQueryCursor? = nil) 
    print("fetchVisits \(cursor)")
    var operation: CKQueryOperation!
    if let cursor = cursor 
        operation = CKQueryOperation(cursor: cursor)
     else 
        let query = CKQuery(recordType: "Visit", predicate: NSPredicate(format: "Client IN %@ AND ANY Students IN %@", visitClients, visitStudents))
        operation = CKQueryOperation(query: query)
    
    operation.recordFetchedBlock = 
        (record) in
        totalVisits.append(record)
    
    operation.queryCompletionBlock = 
        (cursor, error) in
        if let error = error 
            //handle error
         else if let cursor = cursor 
            self.fetchVisits(cursor)
         else 
            //all done!
        
    
    CKContainer.default().publicCloudDatabase.add(operation)

我这样调用函数:

fetchVisits()

效果很好,它可以获得我需要的所有访问。控制台日志

fetchVisits nil
fetchVisits Optional(<CKQueryCursor: 0x174228140; id=4bb7887c326fc719, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422a320; id=f67fb25669486da9, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x174228380; id=7e87eb8b7cfe1a74, zone=(null)>)
fetchVisits Optional(<CKQueryCursor: 0x17422cc80; id=e77e47ef2b29c8a4, zone=(null)>)

但问题是现在我想在按下按钮时刷新,现在它给了我这个错误:

“服务不可用”(6/2022); “请求失败,http 状态码 503”; 30.0 秒后重试

这很不言自明,我想我通过请求区区的 500 条记录来压倒服务器?所以我等了 30 秒,然后再次调用该函数,现在我得到了这个错误。

“超出限制”(27/2023); server message = "查询过滤器超出了值的限制:容器为 250

由于某种原因,我无法再次运行该功能。如果我重新启动应用程序,它会再次正常工作,但只是第一次。这个问题似乎特定于任何返回 CKQueryCursor 的表。我有其他表,我正在访问的记录少于 100 条(因此光标为零),我可以多次提取这些表而不会出现任何问题。

【问题讨论】:

【参考方案1】:

好的,我以前见过这个问题,我相信问题是 CloudKit 服务器上的一个错误。根据我的经验,它与复杂的查询有关。

如果您尝试将谓词更改为:

NSPredicate(value: true)

或者甚至通过删除 ANY 部分来简化您现有的部分,这可能足以修复它。

【讨论】:

刚刚用这个谓词测试了这个: NSPredicate(format: "Client IN %@", visitClients) 现在我可以根据需要多次调用 fetch 而不会出现任何服务器错误。现在获取结果后,我正在对结果进行辅助谓词过滤。这是一种耻辱,因为我现在正在访问服务器并带回比我需要的记录多得多的记录。【参考方案2】:

您在查询操作完成之前向 iCloud 请求更多 CKRecords。

...
operation.queryCompletionBlock = 
    (cursor, error) in
    if let error = error 
        //handle error
     else if let cursor = cursor 
        self.fetchVisits(cursor)
     else 
        //all done!
    

...

函数self.fetchVisits(cursor) 调用在完成块内完成,这意味着您在当前操作完成之前请求更多记录。

可能的解决方案是使用包含 CKQueryCursor 的闭包 (completionHandler),当用户需要更多记录(滚动表或其他任何内容)时,您再次调用 self.fetchVisits 传递在闭包中收到的光标。

【讨论】:

我以为“queryCompletionBlock”是操作的结束?我会修复那块,但我不确定这是否是导致错误的原因。我看到该操作完成了 5 次并检索了我需要的所有记录,但是当我稍后按下按钮再次调用该函数时,我得到了 CloudKit 服务器错误。 嗨@WilliamT。没错,queryCompletionBlock 只执行一次。如果您可以发布更多代码,也许我可以帮助您... 感谢您提供帮助,但我不确定我还能发布多少代码。上面的函数在我第一次运行时效果很好,但在以后的任何时候都会给我服务器错误,没有更多的代码。【参考方案3】:

编辑:我想现在我找到了原因:

虽然我之前的答案(如下)是正确的,但它不适用于这个问题。 到目前为止,我遇到了问题中提到的两个服务器错误,并调查了情况。

我的设置如下: 我想根据谓词中指定的条件下载 iCloud 记录的子集:

let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, doNotDownloadIfOlder)  

这里,doNotDownloadIfOlder 是一组自定义对象。

在某些测试用例中,它们的数量超过 300。我怀疑这可能是错误消息 查询过滤器超出值的限制:容器为 250 的原因。

因此我修改了我的代码:

let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let limit = min(doNotDownloadIfOlder.count, max)
let shortened = Set(Array(doNotDownloadIfOlder)[0 ..< limit])
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, shortened)  

我将 max 设置为低于 300 的测试值。 结果是这样的:

最大 141 max > 250:“超出限制”(27/2023); server message = "查询过滤器超出了值的限制:容器为 250

显然,查询可能存在未记录的服务器限制。奇怪的数字 140 可能与我的自定义对象的大小有关。

上一个答案:

docs 说:

服务器可以随时更改其限制,但以下是 一般准则:

每次操作 400 项(记录或共享) 每个请求 2 MB(不包括资产大小)

如果您的应用收到CKError.Code.limitExceeded它必须拆分 操作一半,然后再次尝试这两个请求

【讨论】:

以上是关于CKError:查询过滤器超出了值的限制:容器为 250的主要内容,如果未能解决你的问题,请参考以下文章

容器因超出内存限制而被 YARN 杀死。使用了 14.8 GB 的 6 GB 物理内存

查询系统字段时出现CKError:拒绝“未知字段'createdAt'”

简单计数查询超出 Impala 内存限制

Pig : 容器在 cdh 5 中使用 oozie 运行超出物理内存限制

服务“gmail.googleapis.com”的配额指标“查询”和限制“每个用户每分钟的查询数”超出配额

缓存容器