3

I'm trying to find all instances of an object that contain a reference to a combination of separate objects in my object graph.

recommendation

may contain one or more of the following three objects:

damageType

areaDamaged

validVehicles

This structure is built from an import of an existing system's file format and I am unable to restructure the object graph.

I'm using an NSPredicate to find all recommendation objects that have a damageType matching a selected damage as follows:

NSFetchRequest *fetchRequestDamages = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Recommendation class])];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY damageType == %@", _currentRecordedDamage.damageType];

But want the filter to return all Recommendations that have matches for a specific damageType, areaDamaged and validVehicle

I've tried

NSMutableArray *predicates = [[NSMutableArray alloc] initWithCapacity:2];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY damageType == %@", _currentRecordedDamage.damageType];
        [predicates addObject:predicate];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"ANY areaDamaged == %@", _currentAreaDamaged];
        [predicates addObject:predicate2];
NSPredicate *predicate3 = [NSPredicate predicateWithFormat:@"ANY validVehicles == %@", _currentVehicle];
        [predicates addObject:predicate3];


fetchRequestDamages.predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];


fetchRequestDamages.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequestDamages managedObjectContext:[RKManagedObjectStore defaultStore].mainQueueManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;

NSError *error;

[self.fetchedResultsController performFetch:&error];
 int resultsFound = self.fetchedResultsController.fetchedObjects.count;

but it seems this returns the set of all objects satisfying any of the predicates - I'd like the set of objects that match all three.

I'm looking into using SUBQUERY but can't quite make sense of how to create this query?

davbryn
  • 7,156
  • 2
  • 24
  • 47
  • What's your code for executing the fetch request? – David Snabel-Caunt Nov 19 '13 at 16:07
  • @davbryn: So you do already what I suggested below. - Perhaps you can show an example of what you get currently and what you expect. – Martin R Nov 19 '13 at 16:26
  • Are damageType and areaDamaged and validVehicles to-many relationships from recommendation? If not simply go with AndrewShmigs. If they are then you will need SubQueries. – Felix Lamouroux Nov 19 '13 at 16:26
  • @FelixLam yes, they are all to-many – davbryn Nov 19 '13 at 16:27
  • Maybe have a look at the response I gave here: http://stackoverflow.com/questions/3725936/core-data-fetch-via-specific-property-join-relationship/3745585#3745585 – Felix Lamouroux Nov 19 '13 at 16:31
  • A SUBQUERY helps if you have a single to-many relationship and you want to test several attributes of the related objects. Here (if I see it correctly) you have three different to-many relationships where each related object has a single attribute to check. – Martin R Nov 19 '13 at 16:34
  • @MartinR that does sound like it makes a lot of sense, when you compare the adapted code example below it looks overly complicated and too simple compared to the original answer i linked to above. – Felix Lamouroux Nov 19 '13 at 16:37

2 Answers2

5

Just combine the three predicates with "AND" to find the objects that match all of them:

NSArray *predicates = ... // your array of predicates
NSPredicate *finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];
[fetchRequestDamages setPredicate:finalPredicate];    
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • When I have the three AND predicates it returns a set that contains recommendations that don't have a validVehicle match in it's set (but does have a match for another property). – davbryn Nov 19 '13 at 16:26
  • 1
    @davbryn: That is strange. It should return only objects that satisfy all three sub-predicates. - Have you tested all three predicates separately? – Martin R Nov 19 '13 at 16:29
  • Is that not what he does in his code? `fetchRequestDamages.predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates];` – Felix Lamouroux Nov 19 '13 at 16:35
  • 1
    @FelixLam: Yes, but I knew that only after he updated the question with this information. – Martin R Nov 19 '13 at 16:37
  • This answer is correct - the problem (regrettably) was that the predicates all matched as they should - there was an importer error that was linking the object to all three requirements. I spotted it by running the predicates individually and investigating the relationships – davbryn Nov 20 '13 at 12:11
2

Why not to use AND in one query? Something like:

damage = %@ AND damagePoints = %@ AND damageCost = %@

and:

damageType IN %@

Where %@ in the last code example should be an array/set or something else.

AndrewShmig
  • 4,843
  • 6
  • 39
  • 68