Navigating the Core Data Object Graph
I asked a question yesterday where I really should have started with a simpler example. Having distilled my question to the basics, I’ve managed to solve my problem using existing SO questions and answers.
I’m summarising my question here (and providing my own solution) because I don’t think there are any posts that explain this clearly enough. Being new to Core Data and struggling to get away from SQL concepts, I’d welcome feedback on how appropriate my solution is, and if there are better ways of modelling the problem.
Given the following object model, that has three entities A, B and C, each linked by to-many relationships:
How is it possible to identify the parent A entities, that have grandchildren C entities with a particular attribute? By example, using these sample entities and their relationships:
How can I find our which entity A s have child entity C s with the Tag:Yes?
I’ve been able to achieve this is using the
SUBQUERY keyword of
NSPredicate. Here is the code snippet that worked for me (assuming you’ve set up your managed object context etc):
NSError *error = nil; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"EntityA" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:@"(0 != SUBQUERY(child, $a, (0 != SUBQUERY($a.child, $child, $child.tag == %@).@count)).@count)", @"YES"]; [fetchRequest setPredicate:predicateTemplate]; NSArray *test = [context executeFetchRequest:fetchRequest error:&error];
Breaking the all important NSPredicate string onto several lines:
(0 != SUBQUERY(child, $a, (0 != SUBQUERY($a.child, $child, $child.tag == %@).@count) ).@count )
The important part is we are selecting the
EntityA to work from and then in the nested subquery working through the
child relationships of the entities. I expect this can be repeated for several depths. Not the most intuitive thing to put together… but it works. Comments welcome.
- How to use NSPredicate to filter NSMutableSet which contains composite object from other Class?
- iphone & Objective C - Filtering an array using NSPredicate?
- How to join two strings for NSPredicate, ie firstname and lastname
- how to build a NSPredicate filtering all days in a month using NSDate?
- Swift coreData - format date and use it in predicate
- NSPredicate Aggregate Operations with NONE
2 Solutions Collect From Internet About “Navigating the Core Data Object Graph”
I’ve never tried to use a subquery before, that’s very cool and good to see an example of it. You should add the solution as an answer to the question actually!
I would have probably done as Abizern suggested, since this is a tree-like hierarchy and its easier to traverse up the tree using to-one relationships.
In code this looks like:
NSManagedObjectContext *moc = APPDELEGATE.managedObjectContext; NSFetchRequest *request = [NSFetchRequest new]; [request setEntity:[NSEntityDescription entityForName:@"EntityC" inManagedObjectContext:moc]]; [request setPredicate:[NSPredicate predicateWithFormat:@"tag = YES"]]; NSError *fetchError = nil; NSArray *children = [moc executeFetchRequest:request error:&fetchError];
children is an array of
EntityC objects that match the predicate. The next step is getting a set of unique
EntityA objects that are the “grandparents” of these. We can take advantage of key-value coding here:
NSArray *grandParents = [children valueForKeyPath:@"parent.@distinctUnionOfObjects.parent"];
In this case, for efficiency, we’d probably want to prefetch the
parent.parent keypath during our initial fetch request:
Hope this helps!
If you’ve followed the Core Data Guidelines and have set up reciprocal relationships you could try searching from the bottom up.
Fetch the Entity C objects that pass your required predicate and then get the Entity A object by going up the parents. No need for nested subqueries.
Edited to add
You can get the parent of C (which is an object of B) from the
parent relationship. And from there you can get the parent (which is an object of A) form the
It’s in your Core Data Model Diagram.
- Display UIAlertController from UIView/NSObject class
- Running iOS App in background for more than 10 minutes
- Update my app when it is in background
- Releasing unused pages in UIPageViewController
- Objective C equivalent of PHP range function?
- App Crashes after executing background fetch completionHandler
- How to detect an iOS App has been re-installed (from XCode) or upgraded (from AppStore)
- Objects not being added to NSMutableArray Objective -C
- How to hide custom tab bar button when hidesBottomBarWhenPushed is “TRUE”
- Cropping a captured image exactly to how it looks in AVCaptureVideoPreviewLayer
- Is it possible to create mutable versions of objects read in from a plist
- UINavigationController and presenting a modal controller
- Verifying user is authenticated using AWS IOS SDK
- Why doesn't the background colour of my Storyboard in Xcode change? It's always the same grey color?
- How to access a UITextView on another ViewController