views:

47

answers:

2

Lets say I have a model similar to the one below, and I need to Fetch all 'Person' of a specific Company.companyName sorted by personRole.roleWeight

This is the model I have at the moment:

  • Entity: Company
  • Attributes: companyName
  • Relationships: companyRole

  • Entity: Role

  • Attributes: roleName, roleWeight
  • Relationships: rolePerson, RoleCompany

  • Entity: Person

  • Attributes: personName
  • Relationships: person Role

Here is a simple diagram of the relationship:

Company --< Role >--< Person

Is there a way to do this? If I need to modify the model I would be happy to do so. All suggestions are welcome.

Thanks,

+1  A: 

You can't sort by role weight because it is possible to have more than one role that fits.

You also can't come at it from the Role (as opposed to the Person) because you have a many-to-many between role and person.

You should re-think your design because having that many-to-many there does not make much sense. A little bit of data de-normalization, changing that many-to-many to a one-to-many and duplicating the rolename and roleweight values would solve the issue.

Update

Assuming you changed the design to:

Company --< Role >-- Person

Then the solution gets much easier:

- (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;
}

You basically fetch the Role entities sorted by weight and filtered by the company name. From that array of Role entities you then use KVC to gather all of the person objects on the other end of the relationship which will retrieve them in order.

Marcus S. Zarra
Hi Marcus, a person could only have 1 role at a specific company. Would it be possible to fetch the role entities for a specific company, and from those roles, get the people that are associated to them? My main goal is to be able to sort the people of a company by their role weight at that company, maybe you can suggest me a better design that would make this task easier. Many thanks.
Benjamin Ortuzar
A: 

Is there a reason that Role is the monkey in the middle and not person? It would make this task easier but maybe you have other things you are doing with the data that precludes this option. If each person had one role and one company you could then create a sort descriptor for role.roleWeight and use NSSet's sortedArrayUsingDescriptors: method on the Company in question's employees relationship set. That would give you a new sorted array with a list of all the Person entities attached to a given Company sorted by roleWeight (you might want to include a secondary sort descriptor to take care of matching roleWeights).

theMikeSwan