Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Complex Core Data predicate with to-many relation

I have 3 entities. Folder, Feed & FeedItem

I need to fetch Folders which have feeds and feeds which have unread FeedItems

NSPredicate * predicate = [NSPredicate predicateWithFormat:@" feeds.@count > 0 AND feeds.feedItems.unread == 0 "];

I get this error

'NSInvalidArgumentException', reason: 'to-many key not allowed here'

How do I construct such a predicate? Is it possible at all?

like image 408
Shuja Shabandri Avatar asked Aug 15 '10 12:08

Shuja Shabandri


1 Answers

It doesn't like feeds.feedItems.unread==0 because feeds and feedItems return a set so the predicate doesn't know which object to test.

Try ANY feeds.feedItems.unread==0.

However, you're going about this backwards. It would be easier to fetch all FeedItem where unread==0 and then ask for each fetched item's feed.folder to get the folder.

Complex predicates are usually a bad idea because you can never predict the resource consumption of the search they perform as the object graph grows in complexity and the data itself grows in size. You should walk relationships instead when you can.


Update:

Looking at this again it looks like you need a SUBQUERY. Try:

NSPredicate *p = [NSPredicate predicateWithFormat:@"(0 != SUBQUERY(feeds, $x, (0 != SUBQUERY($x.feedItems, $y, $y.unread==0).@count)).@count)"];

Subqueries are poorly documented but they are essentially nested predicates. They have the format:

SUBQUERY(objects, singleObjectVariable, expression-for-single-object)

I believe that subqueries return sets so you can use any of the set operators on them and you can nest them. When you nest them, they walk the relationship graph so you can make them arbitrarily deep.

like image 102
TechZen Avatar answered Nov 15 '22 13:11

TechZen