Search code examples
ioscore-datamany-to-manynspredicateany

CoreData NSPredicate with two one-to-many relations


I have a CoreData model data structure like this for restricting information based on the group a user belongs to:

Category <->> Information <->> Groups.

I have an NSSet of UserGroups objects. I want to be able to filter categories based on the NSSet of Group objects, such that if a category does not contain any pieces of information which have any groups inside my NSSet, they will not be returned by my predicate.

For information I can do

[NSPredicate predicateWithFormat:@"ANY groups in (%@)",groups];

For categories I've tried the following with only a crash:

[NSPredicate predicateWithFormat:@"ANY information.groups in (%@)",groups];

But I need to write a predicate at the Category level. I am programming under the assumption that the information in my data set is sufficiently large that I cannot pull them all of them out and process them to find my Categories. I want to create predicate that will fetch only the categories that are relevant to the user based on his/her groups.

Thanks for your help!


Solution

  • The following predicate on Category should work (assuming that information is the to-many relationship from Category to Information):

    [NSPredicate predicateWithFormat:@"SUBQUERY(information, $i, ANY $i.groups in %@).@count > 0",groups];
    

    Alternatively, you could use the inverse relationships:

     // your set of Group objects:
     NSSet *groups = ...;
     // all Information objects that are related to any group object:
     NSSet *information = [groups valueForKey:@"information"] ;
     // all Category objects that are related to any information object:
     NSSet *categories = [information valueForKey:@"category"];
    

    which can be combined to

     NSSet *categories = [groups valueForKeyPath:@"information.category"];
    

    A disadvantage of this alternative solution might be that it creates also the intermediate set of groups in memory.