I have a Core Data object with several attributes, one of which is called Category. This is a string that could take on any value, nothing that I can guarantee any knowledge of up front. I want to run a fetch that will return a list of Category values that are shared across all stored elements whose Tag value matches a given value. I'm not sure how to best describe this, so here's an example:
ObjectNumber Tag Category
---------------------------------
01 AAA Red
02 AAA Green
03 AAA Blue
04 BBB Blue
05 BBB Red
06 BBB Yellow
07 CCC Blue
08 CCC Yellow
09 CCC Red
I want the results of my fetch to be a list of Categories that are shared across all objects whose Tag is in the set {AAA, BBB, CCC}, which in this case, would return ["Red", "Blue"], because those are the only categories shared among any objects whose tag is in the given set.
I'm hoping to find something that's as fast as possible, because when this app is run on a real project, there will be tens of thousands of objects in the database.
Here is a code sample I just wrote up, that should solve your filtration question.
I'm still learning the intricacies of NSFetchRequest and predicates, although it's not very complicated, after reading the documentation and experimenting.
NSArray *setoftags = [NSArray arrayWithObjects: @"AAA", @"BBB", nil];
NSFetchRequest * request;
NSMutableSet *tagcategoriesset = nil;
for (NSString *tag in setoftags) {
request = [NSFetchRequest fetchRequestWithEntityName:@"ObjectWithCategories"];
NSPredicate *tagPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"Tag", tag];
request.predicate = tagPredicate;
NSArray *objects;
NSError *err;
NSMutableSet *tagcategories = [[NSMutableSet alloc] initWithCapacity:1];
if ( (objects = [self.managedObjectContext executeFetchRequest:request error:&err]) == nil) {
// error
NSLog(@"There was an error:\n%@", [err localizedDescription]);
}
else {
// fetch request succeeded
// Ignore any unused tags
if ( [objects count] == 0) continue;
// Collect the Category attribute into a mutable set
for(NSManagedObject *obj in objects) {
[tagcategories addObject: [(id)obj Category]];
}
// First assign, later intersect the tagcategories
if (tagcategoriesset == nil) {
tagcategoriesset = tagcategories;
}
else {
[tagcategoriesset intersectSet: tagcategories];
}
}
}
NSArray *finalCategories = [tagcategoriesset allObjects];
Here's another SO Q&A for further discussion: using NSPredicate with a set of answers