Выборка и сортировка объектов в Core Data

Допустим, у меня есть модель, аналогичная приведенной ниже, и мне нужно получить всех «лиц» определенного Company.companyName, отсортированных по personRole.roleWeight.

Вот такая модель у меня на данный момент:

  • Субъект: Компания
  • Атрибуты: название компании
  • Отношения: компанияРоль

  • Сущность: Роль

  • Атрибуты: имя_роли, вес_роли.
  • Отношения: rolePerson, RoleCompany

  • Сущность: Человек

  • Атрибуты: имя человека
  • Отношения: человек Роль

Вот простая схема отношений:

Компания --‹ Роль >--‹ Лицо

Есть ли способ сделать это? Если мне нужно изменить модель, я был бы рад это сделать. Все предложения приветствуются.

Спасибо,


person Benjamin Ortuzar    schedule 01.07.2010    source источник


Ответы (2)


Вы не можете сортировать по весу роли, потому что может быть более одной подходящей роли.

Вы также не можете прийти к этому из роли (в отличие от человека), потому что у вас есть много ко многим между ролью и человеком.

Вы должны переосмыслить свой дизайн, потому что многие ко многим не имеют особого смысла. Небольшая денормализация данных, изменение отношения «многие ко многим» на «один ко многим» и дублирование значений имени роли и веса роли решит проблему.

Обновлять

Предположим, вы изменили дизайн на:

Company --< Role >-- Person

Тогда решение становится намного проще:

- (NSArray*)peopleSortedByWeightInCompany:(NSString*)company inManagedObjectContext:(NSManagedObjectContext*)moc
{
  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  [request setEntity:[NSEntityDescription entityForName:@"Role" inManagedObjectContext:moc]];
  [request setPredicate:[NSPredicate predicateWithFormat:@"company.name == %@", companyName]];

  NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"weight" ascending:YES];
  [request setSortDescriptors:[NSArray arrayWithObject:sort]];

  NSError *error = nil;
  NSArray *roles = [moc executeFetchRequest:request error:&error];
  [request release], request = nil;
  NSAssert2(roles != nil && error == nil, @"Error fetching roles: %@\n%@", [error localizedDescription], [error userInfo]);

  NSArray *people = [roles valueForKeyPath:@"@distinctUnionOfObjects.person"];

  return people;
}

Вы в основном выбираете объекты ролей, отсортированные по весу и отфильтрованные по названию компании. Затем из этого массива сущностей ролей вы используете KVC для сбора всех объектов-лиц на другом конце отношения, которые будут извлекаться по порядку.

person Marcus S. Zarra    schedule 02.07.2010
comment
Привет, Маркус, у человека может быть только 1 должность в определенной компании. Можно ли получить объекты ролей для конкретной компании и из этих ролей получить людей, которые с ними связаны? Моя главная цель - иметь возможность сортировать людей в компании по весу их ролей в этой компании, возможно, вы можете предложить мне лучший дизайн, который облегчит эту задачу. Большое спасибо. - person Benjamin Ortuzar; 02.07.2010

Есть ли причина, по которой Роль — это обезьяна посередине, а не человек? Это облегчило бы эту задачу, но, возможно, у вас есть другие действия, которые вы делаете с данными, что исключает этот вариант. Если бы у каждого человека была одна роль и одна компания, вы могли бы создать дескриптор сортировки для role.roleWeight и использовать метод NSSet sortedArrayUsingDescriptors: для набора отношений сотрудников рассматриваемой компании. Это даст вам новый отсортированный массив со списком всех сущностей Person, прикрепленных к данной компании, отсортированных по roleWeight (вы можете включить дополнительный дескриптор сортировки, чтобы позаботиться о сопоставлении roleWeights).

person theMikeSwan    schedule 20.07.2010