Core Data - Simple JOIN-type Fetch
core-data, ios, iphone, objective-c
Solution
The best way would be to use relationships.
This way when you fetch a `Location` you can also access the `LocationCategory` like `myLocation.locationCategory`
You would need to set up your relationsship like so:
(Entity)LocationCategory.(relationship)locations <->> (Entity)Location.(relationship)locationCategory
It's a to-many relationship. Don't forget the inverse either.
Once that's set up you just need to connect relationships up where ever you create the entity instances. Like:
Location *myLocation = ...
LocationCategory *myLocationCategory = ...
myLocation.locationCategoy = myLocationCategory;
Also make sure you are using the same MOC to fetch the objects. I strongly recommend MagicalRecord to easily manage creating objects and fetching in the specified moc.
Problem
I am needing to do a "join"-type operation on two tables/models from my Core Data storage, and I'm having a difficult time finding good examples out there for getting something like this to work. It's fairly simple what I need to do. I have two models/tables: locations and location_categories, where locations contains a location/establishment's details (along with a unique ID), and the location_categories table contains category_id's with associated location_id's. I need to select all the locations where, given a category_id, it joins the two tables/models. If it was straight SQL, it would look like this (and this query does work when I run it against the actual SQLite DB): ``` // pretend we passed in a catID of 29: SELECT * FROM zlocation where zlocid in (select zlocid from zloccategory where zcatid = 29) ``` So as you can see, it's pretty straight-forward. Is there a way to do this without having to do two fetches and for-loops? My current objective-c code to do this is below, and it works fine, but of course it's horribly slow and inefficient, due to a lot of data being in both tables. The for-loops are causing a huge slowdown, and my gut tells me that this work really should be done on the DB/Core-Data side of things: ``` - (NSMutableArray *) fetchLocsWithCatID:(NSString *)catID { NSMutableArray *retArr = [[NSMutableArray alloc] init]; NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; [fetchRequest setEntity:[NSEntityDescription entityForName:MODELNAME_LOCCATEGORIES inManagedObjectContext:context]]; [fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"catID == %@", catID]]; NSError *error; NSArray *locCats = [context executeFetchRequest:fetchRequest error:&error]; NSArray *allLocsArr = [self fetchAllDataForTable:MODELNAME_LOCATION]; // this retrieves contents of entire table for (Location *currLoc in allLocsArr) { for (LocCategory *currLocCat in locCats) { if ([currLoc.locID isEqualToString:currLocCat.locID]) { if (![retArr containsObject:currLoc]) { [retArr addObject:currLoc]; } } } } return retArr; } ``` Any thoughts on whether this is possible with one single predicate/fetch? Or dunno.. maybe there is a more efficient way to join those two NSArrays via the objective-c code? Thanks in advance for any direction you can offer on this!