For a relationship like this:
TagGroups<---->>Tags<<---->>Object
An Object has tags, tags can be grouped by tagGroups.
I have an object, and I want to know all of the TagGroups its Tags belong to.
To construct he predicate, I first tried the following format string:
(SELF is a TagGroup)
NSPredicate* p = [NSPredicate predicateWithFormat:@"%@ IN SELF.tags.objects" , object];
This fails because sets are not traversed ala Key-ValueCoding.
After some research I have found several questions explaining SUBQUERY
Core Data, try to use NSPredicate to filter a toMany relationship set but get the "to-many key not allowed here" error
Core data to-many NSPredicate with AND
These seem to be part of the solution, but unlike these questions I am not testing for a value like "tag.name", but membership within the collection.
So with that in mind I tried this:
NSPredicate* p = [NSPredicate predicateWithFormat:@"%@ IN SUBQUERY(SELF.ta开发者_如何学编程gs, $eachTag,$eachTag.object)" , object];
Which fails to parse (I tried a few other variants unsuccessfully as well)
Any ideas on how to construct this format string properly?
Update:
Also tried it from the other direction:
NSPredicate* p = [NSPredicate predicateWithFormat:@"ALL SUBQUERY(%@.tags,$eachTag,$eachTag.tagGroup)" , anObject];
If you "have an object" i.e. you have a particular managedObject whose entity is Object
then you don't need a predicate. You just need to walk the relationship keypath.
Here is an example implemented with dictionaries by it works the same way with a managed object.
NSDictionary *tagGroup1=[NSDictionary dictionaryWithObjectsAndKeys:@"tagGroupOne",@"name",@"tagGroup1",@"theValue",nil];
NSDictionary *tagGroup2=[NSDictionary dictionaryWithObjectsAndKeys:@"tagGroupTwo",@"name",@"tagGroup2",@"theValue",nil];
NSDictionary *tag1=[NSDictionary dictionaryWithObject:tagGroup1 forKey:@"tagGroup"];
NSDictionary *tag2=[NSDictionary dictionaryWithObject:tagGroup2 forKey:@"tagGroup"];
NSSet *tags=[NSSet setWithObjects:tag1,tag2,nil];
NSDictionary *objD=[NSDictionary dictionaryWithObjectsAndKeys:tags,@"tags",nil];
NSLog(@"tagGroup names=%@",[objD valueForKeyPath:@"tags.tagGroup.name"]);
NSLog(@"tagGroup objects=%@",[objD valueForKeyPath:@"tags.tagGroup"]);
... which outputs:
tagGroup names={(
tagGroupTwo,
tagGroupOne
)}
tagGroup objects={(
{
name = tagGroupTwo;
theValue = tagGroup2;
},
{
name = tagGroupOne;
theValue = tagGroup1;
}
)}
So, really all you need is a line like:
NSSet *tagGroups=[anInstanceOfObject valueForKeyPath:@"tags.tagGroup"];
That's the power of key-value coding.
You would only need a subquery if you were trying to fetch Objects
that had a relationship to a TagGroup
with a particular attribute value.
精彩评论