开发者

Core Data with multiple to Many Predicates

开发者 https://www.devze.com 2023-02-13 06:05 出处:网络
For a relationship like this: TagGroups<---->>Tags<<---->>Object An Object has tags, tags can be grouped by tagGroups.

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消