CKError: Query filter exceeds the limit of values: 250 for container
CKError: Query filter exceeds the limit of values: 250 for container
我想从 public 数据库中提取大约 500 "Visit" 条记录。 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)>)
但现在的问题是我想在按下按钮时刷新,但现在却出现此错误:
"Service Unavailable" (6/2022); "Request failed with http status code 503"; 30.0 秒后重试
这是不言自明的,我想我通过请求区区 500 条记录让服务器不堪重负?所以我等待 30 秒并再次调用该函数,现在我得到了这个错误。
"Limit Exceeded" (27/2023); server message = "Query filter exceeds the limit of values: 250 for container
出于某种原因,我无法再次 运行 该功能。如果我重新启动应用程序,它会再次正常工作,但只是第一次。这个问题似乎特定于任何 table that returns CKQueryCursor。我还有其他 table 我正在点击的记录少于 100 条(因此光标为零),我可以多次拉动这些记录而不会出现任何问题。
在查询操作完成之前,您正在向 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),当用户需要更多记录(滚动 table 或其他)时,您再次调用一个 self.fetchVisits
传递 cursos在您关闭时收到。
好的,所以我以前见过这个,我认为问题是 CloudKit 服务器中的错误。根据我的经验,它与复杂的查询有关。
如果您尝试将谓词更改为:
NSPredicate(value: true)
或者甚至通过删除 ANY 部分来简化现有的,这可能足以修复它。
编辑:我想现在我找到了原因:
虽然我之前的回答(如下)是正确的,但它不适用于这个问题。
至此,我自己遇到了问题中提到的两个服务器错误,并调查了情况。
我的设置如下:
我想根据谓词中指定的条件下载 iCloud 记录的子集:
let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, doNotDownloadIfOlder)
这里,doNotDownloadIfOlder
是一组自定义对象。
在某些测试用例中,它们的数量超过 300。我怀疑这可能是错误消息的原因 Query filter exceeds the limit of values: 250 for container .
我因此修改了我的代码:
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 <= 最大值 <= 250:"Service Unavailable" (6/2022); "Request failed with http status code 503"; 30.0 秒后重试>
- 最大 > 250:"Limit Exceeded" (27/2023); server message = "Query filter exceeds the limit of values: 250 for container
显然,查询可能存在未记录的服务器限制。奇怪的数字 140 可能与我的自定义对象的大小有关。
上一个回答:
docs 说:
The server can change its limits at any time, but the following are
general guidelines:
- 400 items (records or shares) per operation
- 2 MB per request (not counting asset sizes)
If your app receives CKError.Code.limitExceeded
, it must split the
operation in half and try both requests again.
我想从 public 数据库中提取大约 500 "Visit" 条记录。 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)>)
但现在的问题是我想在按下按钮时刷新,但现在却出现此错误:
"Service Unavailable" (6/2022); "Request failed with http status code 503"; 30.0 秒后重试
这是不言自明的,我想我通过请求区区 500 条记录让服务器不堪重负?所以我等待 30 秒并再次调用该函数,现在我得到了这个错误。
"Limit Exceeded" (27/2023); server message = "Query filter exceeds the limit of values: 250 for container
出于某种原因,我无法再次 运行 该功能。如果我重新启动应用程序,它会再次正常工作,但只是第一次。这个问题似乎特定于任何 table that returns CKQueryCursor。我还有其他 table 我正在点击的记录少于 100 条(因此光标为零),我可以多次拉动这些记录而不会出现任何问题。
在查询操作完成之前,您正在向 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),当用户需要更多记录(滚动 table 或其他)时,您再次调用一个 self.fetchVisits
传递 cursos在您关闭时收到。
好的,所以我以前见过这个,我认为问题是 CloudKit 服务器中的错误。根据我的经验,它与复杂的查询有关。
如果您尝试将谓词更改为:
NSPredicate(value: true)
或者甚至通过删除 ANY 部分来简化现有的,这可能足以修复它。
编辑:我想现在我找到了原因:
虽然我之前的回答(如下)是正确的,但它不适用于这个问题。
至此,我自己遇到了问题中提到的两个服务器错误,并调查了情况。
我的设置如下:
我想根据谓词中指定的条件下载 iCloud 记录的子集:
let doNotDownloadIfOlderFormat = "NOT " + iCloudRecordKeyName + " IN %@"
let doNotDownloadIfOlderPredicate = NSPredicate.init(format: doNotDownloadIfOlderFormat, doNotDownloadIfOlder)
这里,doNotDownloadIfOlder
是一组自定义对象。
在某些测试用例中,它们的数量超过 300。我怀疑这可能是错误消息的原因 Query filter exceeds the limit of values: 250 for container .
我因此修改了我的代码:
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 <= 最大值 <= 250:"Service Unavailable" (6/2022); "Request failed with http status code 503"; 30.0 秒后重试>
- 最大 > 250:"Limit Exceeded" (27/2023); server message = "Query filter exceeds the limit of values: 250 for container
显然,查询可能存在未记录的服务器限制。奇怪的数字 140 可能与我的自定义对象的大小有关。
上一个回答:
docs 说:
The server can change its limits at any time, but the following are general guidelines:
- 400 items (records or shares) per operation
- 2 MB per request (not counting asset sizes)
If your app receives
CKError.Code.limitExceeded
, it must split the operation in half and try both requests again.