首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CKError:查询过滤器超过了容器的值限制:250个

CKError:查询过滤器超过了容器的值限制:250个
EN

Stack Overflow用户
提问于 2017-07-27 09:26:51
回答 3查看 664关注 0票数 11

我想从公共数据库中删除大约500个“访问”记录。CloudKit一次只给你100个记录,所以我就像下面这样利用CKQueryCursor来获取我想要的所有记录。

代码语言:javascript
复制
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)
}

我把这个函数称为:

代码语言:javascript
复制
fetchVisits()

很好,它能让我得到所有需要的访问。控制台日志

代码语言:javascript
复制
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);服务器消息=“查询筛选器超过值的限制: 250用于容器

由于某些原因,我不能再次运行该函数。如果我重新启动应用程序,它可以再次正常工作,但只是第一次。此问题似乎特定于任何返回CKQueryCursor的表。我有其他的表,我点击的少于100条记录(所以光标是零),我可以多次拉那些没有任何问题。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-29 17:21:29

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

如果尝试将谓词更改为:

代码语言:javascript
复制
NSPredicate(value: true)

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

票数 5
EN

Stack Overflow用户

发布于 2017-07-27 10:34:16

在查询操作完成之前,您将请求更多的CKRecords到iCloud。

代码语言:javascript
复制
...
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)调用是在完成块中完成的,这意味着在当前操作完成之前,您正在请求更多的记录。

可能的解决方案是使用闭包(completionHandler),其中包含CKQueryCursor,当用户需要更多的记录(滚动一个表或其他什么)时,您再次调用self.fetchVisits,传递在闭包上收到的cursos。

票数 1
EN

Stack Overflow用户

发布于 2019-07-06 13:01:45

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

虽然我先前的回答(以下)是正确的,但它不适用于这个问题。

现在,我遇到了问题中提到的两个服务器错误,并对情况进行了调查。

我的设置如下:

我希望根据谓词中指定的条件下载iCloud记录的子集:

代码语言:javascript
复制
let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, doNotDownloadIfOlder)  

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

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

因此,我修改了代码:

代码语言:javascript
复制
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以下的测试值。

其结果是:

  • max <= 140:无错误
  • 141 <= max <= 250:“服务不可用”(6/2022);“请求失败,http状态代码503";在30.0 seconds>后重试
  • 最大值> 250:“超出限制”(27/2023);服务器消息=“查询筛选器超过值限制: 250用于容器

显然,对于查询,可能存在一个无文档的服务器限制。这个奇怪的数字140可能与我的定制对象的大小有关。

先前的回答:

文档说:

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

  • 每次作业400项(记录或股份)
  • 每个请求2MB(不包括资产大小)

如果应用程序接收到CKError.Code.limitExceeded,则必须将操作拆分成两部分,然后再次尝试请求。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45346613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档