Сложный запрос Core Data - PullRequest
0 голосов
/ 26 ноября 2009

У меня есть модель с полевой датой. Мне нужно получить все записи за весь день года, или если ни одна запись за этот день не была представлена ​​как 0. Теперь я выбираю все записи за год и делаю это вручную. Могу ли я сделать это с помощью запросов к основным данным?

1 Ответ

1 голос
/ 03 декабря 2009

Как правило, в Core Data гораздо быстрее делать все выборки, которые вам понадобятся, а не разбивать их на несколько выборок.

Я пытался посчитать записи по дням года двумя способами:

  1. Получить все записи за год. Найдите отличные даты для этих записей. Зациклите даты и посчитайте записи.

  2. Цикл каждый день в году. Выполните выборку только для записей для записей с этой датой.

При небольшой базе данных (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];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...