我的模型有字段日期。我需要获取一年中所有日期的所有记录数,或者如果今天没有记录提取为0.现在我获取一年中的所有记录并手动制作。我可以使用核心数据查询吗?
答案 0 :(得分:1)
通常在Core Data中,您需要预先完成所有提取操作,而不是将其分解为多次提取。
我试图通过两种方式计算一年中的记录:
获取一年的所有记录。查找这些记录的不同日期。循环日期并计算记录。
在一年中的每一天循环。对具有该日期的记录执行仅计数提取。
使用小型数据库(48条记录),第一种方法的速度提高了约90倍。我想第一种方法的表现会随着更多记录的增加而变得更糟,第二种方法会保持不变。
以下是代码:
- (void)doFullLoadTestWithYear:(int)year {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setDay:1];
[comps setMonth:1];
[comps setYear:year];
NSDate *start = [gregorian dateFromComponents:comps];
[comps setDay:31];
[comps setMonth:12];
NSDate *end = [gregorian dateFromComponents:comps];
NSPredicate *yearPred = [NSPredicate predicateWithFormat:@"date >= %@ && date <= %@",start,end];
[fetchRequest setPredicate:yearPred];
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];
if (error) {
NSLog(@"Error during fetch: %@",[error localizedDescription]);
abort();
}
int dateCount = 0, recordCount = 0;
NSArray *dates = [array valueForKeyPath:@"@distinctUnionOfObjects.date"];
for (NSDate *date in dates) {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"date == %@",date];
NSArray *records = [array filteredArrayUsingPredicate:pred];
dateCount++;
recordCount += [records count];
NSLog(@"%d record(s) with date %@",[records count],date);
}
NSLog(@"Record count for year is %d",recordCount);
NSLog(@"Distinct dates count is %d",dateCount);
}
- (void)doSeparateTestWithYear:(int)year {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDateComponents *comps = [[[NSDateComponents alloc] init] autorelease];
[comps setDay:1];
[comps setMonth:1];
[comps setYear:year];
NSDate *start = [gregorian dateFromComponents:comps];
[comps setYear:year+1];
NSDate *end = [gregorian dateFromComponents:comps];
NSDateComponents *oneDay = [[[NSDateComponents alloc] init] autorelease];
[oneDay setDay:1];
int dateCount = 0, recordCount = 0;
NSDate *date = start;
while (![date isEqual:end]) {
NSPredicate *dayPred = [NSPredicate predicateWithFormat:@"date == %@",date];
[fetchRequest setPredicate:dayPred];
NSError *error = nil;
int count = [self.managedObjectContext countForFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Error during fetch: %@",[error localizedDescription]);
abort();
}
if (count > 0) {
NSLog(@"%d record(s) with date %@",count,date);
dateCount++;
recordCount += count;
}
date = [gregorian dateByAddingComponents:oneDay toDate:date options:0];
}
NSLog(@"Record count for year is %d",recordCount);
NSLog(@"Distinct dates count is %d",dateCount);
[fetchRequest release];
}