views:

58

answers:

1

Given the following Core Data Model:

-> : to-one releationship  
->>: to-many relationship

Entity A ->> Entity B 
Entity B -> A // each B belongs to exactly one A  
Entity B ->> B // a B can be related to other B's

So in class A:

@property (nonatomic, retain) NSSet *Bs;

In class B:

@property (nonatomic, retain) A *A;  
@property (nonatomic, retain) NSSet *Bs; 

Assume I have an NSArray *myArray containing (Bj, Bk).

What I want is to fetch all B's which belong to Ax and are related to Bj and Bk:

The code below works, but is completely ugly, since I have to hardcode the NSPredicate based on the number (here it's 2, but it could be 10 or so) of B's in the array:

NSEntityDescription *fetchedEntity = [NSEntityDescription entityForName:@"B" inManagedObjectContext:self.managedObjectContext];
[NSPredicate predicateWithFormat:@"A == %@ and (Bs contains %@) and (Bs contains %@)", Ax, [myArray objectAtIndex:0], [myArray objectAtIndex:1]];

How can I rewrite the predicate so that it is more generic? It must be so obvious, but I just don't see it...

+1  A: 

Does

[NSPredicate predicateWithFormat:@"A==%@ AND (ALL %@ IN Bs)", Ax, myArray];

do what you expect? I am not sure (and away from my OS X box) whether this predicate is translatable to SQL for the Core Data SQLite engine. You may need a SUBQUERY expression:

[NSPredicate preidcateWithFormat:@"A==%@ and SUBQUERY(Bs, $x, $x IN %@).@count == %d", Ax, myArray, myArray.count];

This assumes that the items in myArray are unique.

Barry Wark
Thx for the quick response. Your first solution raises an Exception: unsupported predicate (null). The second works (had to fix @count and the missing ). But it's very slow. My hardcoded solution takes around 0.012 seconds, whereas the subquery solution takes around 10 seconds...
cardinal
Unfortunately what you're asking for (a general solution) is indirect conflict with an efficient SQL query against a relational engine. I think you have to pick one or the other. What was the syntax error exactly? I will correct the post.
Barry Wark
huh. did you correct the query already? or did i mix your solution with the ones from the SUBQUERY docs? My bad: Your solution works perfectly, sorry, and it rocks, average time is 0.000016 seconds! I think i mixed your solution with one from the docs: NSPredicate *predicate = [NSPredicate predicateWithFormat:@"A == %@ and (SUBQUERY(Bs, $x, $x IN %@).@count == Bs.@count)", Ax, myArray, myArray.count]; This one is really bad, taking around 10 seconds average. Because of the Bs.@count! Thank you very much, saved my day!
cardinal