核心数据复杂查询

时间:2009-11-25 21:19:11

标签: core-data

我的模型有字段日期。我需要获取一年中所有日期的所有记录数,或者如果今天没有记录提取为0.现在我获取一年中的所有记录并手动制作。我可以使用核心数据查询吗?

1 个答案:

答案 0 :(得分:1)

通常在Core Data中,您需要预先完成所有提取操作,而不是将其分解为多次提取。

我试图通过两种方式计算一年中的记录:

  1. 获取一年的所有记录。查找这些记录的不同日期。循环日期并计算记录。

  2. 在一年中的每一天循环。对具有该日期的记录执行仅计数提取。

  3. 使用小型数据库(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];
    }