views:

48

answers:

1

I have modeled a Person/Tag relationship. It's a many to many relationship; a person can have multiple tags and a tag can be associated to multiple people.

I am trying to run a query to see get a list of people, that have been tagged with EVERY tag of a set of tags. For Example: Every person that has been tagged with 'FOO' and 'BAR'.

This is the code I was trying with no success.

NSPredicate *attributePredicate = [NSPredicate predicateWithFormat: 
                                       @"ALL personTags.tagName in %@", filtersArray];
[subPredicates addObject:attributePredicate];;

Is there any way around this? I'm using SqlLite as the persistent store. I have around 2000 people in the database and around 100 different tags, only a few would tags applied at the same time.

+1  A: 

Reverse your query and ask for tags that are "self in %@" and you can then perform a KVC operation on the resulting array like:

    NSArray *array = [results valueForKeyPath:@"@distinctUniionOfArrays.person"];

Which will give you the results you are looking for.  Note that this was typed onto my iPad so typos are probable.

See the documentation on this subject

http://developer.apple.com/mac/library/iPad/index.html#documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/ArrayOperators.html

Update

Sorry, I had misread the question. I would suggest trying a subquery. Without access to your data structure it is hard to test this to get it exactly right but this code should put you on the right path:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:moc]];
[request setPredicate:[NSPredicate predicateWithFormat:@"(SUBQUERY(self.tags, $tag, ALL $tag.name in %@).count > 0)", tagNameArray]];

NSError *error = nil;
NSArray *results = [moc executeFetchRequest:request error:&error];
NSAssert2(error == nil, @"Error fetchings tags: %@\n%@", [error localizedDescrption], [error userInfo]);
Marcus S. Zarra
Hi Markus, I gave this a try, but @distinctUnionOfSets returns the union between two or more sets. What I need is the intersection between these sets. Any suggestion for this?
Benjamin Ortuzar
You are a genius! This works perfectly: NSPredicate *attributePredicate = [NSPredicate predicateWithFormat: @"(SUBQUERY(self.personTags, $tag, $tag.tagName IN %@).@count > %d)", filtersArray, [filtersArray count]-1];
Benjamin Ortuzar