Parse.com 查询 10000 (10K) 个对象
Posted
技术标签:
【中文标题】Parse.com 查询 10000 (10K) 个对象【英文标题】:Parse.com query for 10000 (10K) objects 【发布时间】:2014-07-30 09:53:36 【问题描述】:我有一个解析数据库,其中包含一个名为 MeetingObject
的类,其中填充了 6000 个对象(顺便说一下,它会增长...)。
作为解析查询限制 1000,我正在尝试使用跳过查询属性来获取它们。
以下代码给了我 2000 个对象:
NSMutableArray *allObjects = [NSMutableArray array];
NSUInteger limit = 1000;
__block NSUInteger skip = 0;
[query setLimit: limit];
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
if (!error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
if (objects.count == limit)
// There might be more objects in the table. Update the skip value and execute the query again.
skip += limit;
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
];
else if (error || [error code] == kPFErrorConnectionFailed)
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error!" message:NSLocalizedString(@"The Internet connection appears to be offline.",@"no internet") delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok", nil];
self.navigationItem.rightBarButtonItem.enabled = YES;
self.tableView.userInteractionEnabled = YES;
[alertView show];
return;
];
我的理解是,如果我想再获得 1000 个对象,我必须添加另一个嵌套查询,然后再添加一个用于下一个 1000 的对象,依此类推:
// finding the first 1000 objects
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
if (!error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
if (objects.count == limit)
// finding another 1000 objects
skip += limit;
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
if (objects.count == limit)
// finding another 1000 objects
skip += limit;
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
];
];
但是如果我不知道对象的确切数量怎么办?我尝试使用:
while (objects.count == limit)
// There might be more objects in the table. Update the skip value and execute the query again.
skip += limit;
[query setSkip: skip];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
[allObjects addObjectsFromArray:objects];
NSLog(@"%lu", (unsigned long)allObjects.count );
];
但我明白了
* 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“此查询具有未完成的网络连接。你必须等到它完成。'
因为当然查询是在最后一个完成之前进行的......
【问题讨论】:
此链接回答您的问题:parse.com/questions/paging-through-more-than-10000-results 【参考方案1】:虽然这是一个较晚的响应,但这可以帮助遇到此问题的其他人。 基本上,就像上面西蒙的回答一样,第 1 步是获取计数,然后创建一个组调度以循环遍历每个请求,直到所有数据都已下载。这是我使用的(稍微通用的)代码:
- (void)getLargeDataFromParseWithBlock:(void (^)(NSArray *, NSError *))block
int max = 1000;
__block NSError *error;
PFQuery *query = [PFQuery queryWithClassName:@"<your class>"];
[query whereKey:@"<field name in class>" equalTo:@"xyz"];
query.limit = max;
// get count of ojects first
[query countObjectsInBackgroundWithBlock:^(int count, NSError *_error)
if (!error)
// calculate how many requests are need based on count and max
int APIrequests = (count+max-1)/max;
// create a group dispatch
dispatch_group_t downloadGroup = dispatch_group_create();
for (int i=0; i<APIrequests; i++)
// tell dispatch a task is starting
dispatch_group_enter(downloadGroup);
PFQuery *dispatchQuery = [PFQuery queryWithClassName:@"<your class>"];
[dispatchQuery whereKey:@"<field name in class>" equalTo:@"xyz"];
dispatchQuery.limit = max;
dispatchQuery.skip = i*max;
[dispatchQuery findObjectsInBackgroundWithBlock:^(NSArray *arrayResponse, NSError *_error2)
if (!_error2)
NSLog(@"Successfully retrieved %lu.", (unsigned long)arrayResponse.count);
// do something with arrayResponse like add to core data or sqlite
// tell dispatch task has completed
dispatch_group_leave(downloadGroup);
else
NSLog(@"Error: %@ %@", _error2, [_error2 userInfo]);
error = _error2;
// tell dispatch task has completed - need to cover suuccess and fail scenarios of parse request
dispatch_group_leave(downloadGroup);
];
// called when no more tasks in dispatch
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^
if (block)
if (!error)
// array could contain combined responses - sourced from core data or sqlite for example
block(@[], nil);
else
block(nil, error);
);
else
block(nil, _error);
NSLog(@"Count error: %@ %@", _error, [_error userInfo]);
];
【讨论】:
【参考方案2】:我要做的是先获取对象的数量,然后使用 skip 方法进行查询。
PFQuery *query = [PFQuery queryWithClassName:@"GameScore"];
[query whereKey:@"playername" equalTo:@"Sean Plott"];
[query countObjectsInBackgroundWithBlock:^(int count, NSError *error)
if (!error)
dispatchFindObjectsUsingLimit(count)
else
// The request failed
];
【讨论】:
以上是关于Parse.com 查询 10000 (10K) 个对象的主要内容,如果未能解决你的问题,请参考以下文章
parse.com - 如何使用 PHP SDK 从 parse.com 查询和获取类似数组的 json?