tierfour
tierfour

Reputation: 682

Predicate for Many-To-Many

Trying to wrap my head around predicates and core data. I have a model that looks like this.

House <-->> Room (House has many rooms)
Room <<-->> Fixtures (rooms have many fixtures and many fixtures can belong to rooms)
Fixtures <-->> Fixture_Types (fixtures have many types)

What should my predicate look like if I have the "House" and I need to get all unique Fixture_types where "room" == "kitchen" (or whatever).

Thanks!

Upvotes: 2

Views: 318

Answers (1)

tierfour
tierfour

Reputation: 682

I think I figured it out. Here is what I did.

Get the top level object House and its child room - kitchen.

Room *room = [house.rooms objectAtIndex:someIndex]; 

I have a display order, so set:

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];

I have a helper function to get objects with a defined predicate, so:

+(NSArray *)objectsForEntityNamed:(NSString *)name withPredicate:(NSPredicate *)predicate inContext:(NSManagedObjectContext *)context{
    NSEntityDescription *entity = [NSEntityDescription entityForName:name inManagedObjectContext:context];

    NSFetchRequest *req = [[NSFetchRequest alloc] init];
    [req setEntity:entity];
    [req setPredicate:predicate];
    NSError *error = nil;

    NSArray *array = [context executeFetchRequest:req error:&error];

    if (array == nil){
        NSException *exception = [NSException exceptionWithName:CoreDataExeption reason:[error localizedDescription] userInfo:nil];

        [exception raise];

    }
    return array;

}

And now for the good stuff, where fixture_types in the predicate is the inverse relationship of Fixture_Types to Fixtures. Of course, you can do a distinct but since my db is normalized I should only get unique results anyway:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"ANY fixture_types IN %@", room.fixtures];

NSArray *fixture_types = [[CDUtilities objectsForEntityNamed:@"Fixture_Types" withPredicate:pred inContext:[house managedObjectContext]] sortedArrayUsingDescriptors:[[NSArray alloc] initWithObjects:descriptor, nil]];

Hope this helps someone, let me know if there is a better way to do this or if you have question on how I did it.

Upvotes: 1

Related Questions