Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do Core Data queries through a relationship?

I'm messing around with Core Data, and I am sure I am missing something obvious, because I cannot find an example that at all resembles what I am trying to do.

Let's say I'm playing around with a DVD database. I have two entities. A Movie (title, year, rating, and a relationship to Actor) and Actor (name, sex, picture).

Getting all the Movies is easy. It's just:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Winery"
inManagedObjectContext:self.managedObjectContext];

Getting all the Movies with "Kill" in the title is easy, I just add a NSPredicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"name LIKE[c] "*\"Kill\"*""];

But Core Data seems to abstract out the id fields for the managed objects... so how to I query against an attribute that is an object (or: query against a relationship)?

In other words, assuming that I already have the Actor object I am concerned with ([Object id 1 - 'Chuck Norris'] for instance), what is the Predicate format for "Give me all movies starring [Object id 1 - 'Chuck Norris']"?

like image 286
mmc Avatar asked May 09 '09 21:05

mmc


2 Answers

Assuming that there is a one-to-many inverse relationship between the Actor and the Movie entities, you can just get the entity for Chuck Norris the same way you would get any specific entity, and then access the array of Movie entities attached to the relationship on the Actor entity.

// Obviously you should do proper error checking here... but for this example
// we'll assume that everything actually exists in the database and returns
// exactly what we expect.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Actor" inManagedObjectContext:self.managedObjectContext];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name LIKE[c] 'Chuck Norris'"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];

// You need to have imported the interface for your actor entity somewhere
// before here...
NSError *error = nil;
YourActorObject *chuck = (YourActorObject*) [[self.managedObjectContext executeFetchRequest:request error:&error] objectAtIndex:0];

// Now just get the set as defined on your actor entity...
NSSet *moviesWithChuck = chuck.movies;

As a note, this example obviously assumes 10.5 using properties, but you can do the same thing in 10.4 using accessor methods.

like image 163
Jason Coco Avatar answered Oct 04 '22 12:10

Jason Coco


Or you can use another predicate:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Actor" inManagedObjectContext:self.managedObjectContext];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",@"Chuck Norris"]
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entity];
[request setPredicate:predicate];

YourActorObject *chuck = [[self.managedObjectContext executeFetchRequest:request error:nil] objectAtIndex:0];
[request release];

NSSet *moviesWithChuck = chuck.movies;
like image 24
Igor Avatar answered Oct 04 '22 10:10

Igor