views:

148

answers:

1

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?

+4  A: 

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.

TechZen
I tried this, but get exception 'multiple to-many keys not allowed here'. The reason i cannot do it backwards is because feedItems could be huge.
Shuja Shabandri
See my update for a better answer.
TechZen
Tried the subquery method. getting this error Unable to generate SQL for predicate (0 != SUBQUERY(feeds, $x, 0 != SUBQUERY($x.feedItems, $y, $y.unread == 0).@count).@count) (problem on RHS)'
Shuja Shabandri
You dropped a parenthesis. It should be '(0 != SUBQUERY(feeds, $x, ...(...0 != SUBQUERY($x.feedItems, $y, $y.unread == 0).@count).@count)` where "..." delineates the missing paren.
TechZen