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 的测试值。
结果是这样的:
显然,查询可能存在未记录的服务器限制。奇怪的数字 140 可能与我的自定义对象的大小有关。
上一个答案:
docs 说:
服务器可以随时更改其限制,但以下是 一般准则:
每次操作 400 项(记录或共享) 每个请求 2 MB(不包括资产大小)如果您的应用收到
CKError.Code.limitExceeded
,它必须拆分 操作一半,然后再次尝试这两个请求。
【讨论】:
以上是关于CKError:查询过滤器超出了值的限制:容器为 250的主要内容,如果未能解决你的问题,请参考以下文章
容器因超出内存限制而被 YARN 杀死。使用了 14.8 GB 的 6 GB 物理内存
查询系统字段时出现CKError:拒绝“未知字段'createdAt'”
Pig : 容器在 cdh 5 中使用 oozie 运行超出物理内存限制