Compound AND predicate for many to many relationship using SUBQUERY

I have an entity A with a many to many relationship "events" with entity Event. Entity Event has an attribute eventName.


I want to be able to fetch all entity As that have a given set of Event entitys that match the entityName selected by the user. For an ANY fetch, a compound OR predicate works fine. But for an ALL fetch (where only entity As that have ALL of the user chosen events will be fetched) the compound AND predicate returns a nil!


I was told that I would have to use subqueries. My deliema is that I am having a hard time figuring out how to form a subquery string.


The format is as follows...


SUBQUERY(collection_expression, variable_expression, predicate);


I'll have the eventName string selected by the user so that is dynamic. So what should my subquery look like if I want to use the LIKE[d] operator?


the collection_expression would be the relationship "events" if i am not wrong?


kindly help me out with this.


thankyou.

Accepted Reply

In reverse order:


Go to the "Content" link, https://forums.developer.apple.com/content

The threads you've created should show up under 'Authored'. The threads you've posted in should show up under 'Participated'.


For

(SUBQUERY(events,$x, $x.event LIKE[d] %@))

it's important to understand that it's an expression which evaluates to a collection, not a single boolean value. That means that


(SUBQUERY(events,$x, $x.event LIKE[d] %@))

by itself isn't a valid predicate because doesn't evaluate to a boolean value. You need to embed the subquery expression in a complete boolean expression like


(SUBQUERY(events,$x, $x.event LIKE[d] %@)).@count > 0

Replies

here is what my predicate looks like...


NSPredicate *eventEqualToPredicate = [NSPredicate predicateWithFormat:@"(SUBQUERY(events,$x, $x.event LIKE[d] %@))",event ];


and the error message is as follows...


*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "(SUBQUERY(event,$x, $x.event LIKE[d] %@))


by the way, does anyone know how to see all the posts i have made or threads i have started in these new forums?!!

In reverse order:


Go to the "Content" link, https://forums.developer.apple.com/content

The threads you've created should show up under 'Authored'. The threads you've posted in should show up under 'Participated'.


For

(SUBQUERY(events,$x, $x.event LIKE[d] %@))

it's important to understand that it's an expression which evaluates to a collection, not a single boolean value. That means that


(SUBQUERY(events,$x, $x.event LIKE[d] %@))

by itself isn't a valid predicate because doesn't evaluate to a boolean value. You need to embed the subquery expression in a complete boolean expression like


(SUBQUERY(events,$x, $x.event LIKE[d] %@)).@count > 0

Hi NotMyName,


Nice seeing you back on these new forums.


I'm glad I got a part of the subquery right. now what does .@count>0 do?

this is what my final predicate looks like when two events are selected...


SUBQUERY(event, $x, $x.event LIKE[d] "Birthday").@count > 0 AND SUBQUERY(event, $x, $x.event LIKE[d] "party").@count > 0


now i have one entry with both these events but i get nil returned on executing the fetch request.


i guess my original AND compound predicate was right. there seems something wrong with my persistent store.


any idea what it could be?

@count is one of the collection operators, it evaluations the size of the collection.


So the SUBQUERY(............).@count > 0 is a predicate for whether there are any matches to the subquery.

I'm pretty sure you can't actually have a string value that matches two LIKE clauses like that without specify a wildcard in both of them.

Because you're expected to supply the wildcards:

LIKE
The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.


In other words, if you're trying to match "Birthday party" you need soething like "Birthday*" and "*party" as your two target values, or "*birthday*" and "*party*".


More importantly, if you're trying to make sure the same event matches both "Birthday*" and "*party" then you need


SUBQUERY(event, $x, $x.event LIKE[d] "Birthday*" && $x.event LIKE[d] "*party").@count > 0

That's the more common use for subquery, by the way. When you have one of the objects in the event to-many relationship and you want to make sure that the same object satisfies multiple criteria.


The way you have it specified it,

SUBQUERY(event, $x, $x.event LIKE[d] "Birthday*").@count > 0 AND SUBQUERY(event, $x, $x.event LIKE[d] "*party").@count > 0

with the added wildcards, if you "Birthday planning" and "Office party" as two different events, your predicate would match.

birthday and party are two separate events and they both could be selected in a single entry and it doesnt reduce to a single event called 'birthday party'. Using this app called 'Core Data Editor' I found out that my code was only taking one event where multiple are selected. So my store didnt have any entry with two events Birthday and Party! I guess I found where the bug is.

my orginial code...


                NSPredicate *eventEqualToPredicate= [NSComparisonPredicate predicateWithLeftExpression:eventLHS rightExpression:eventRHS modifier:NSAnyPredicateModifier type:NSLikePredicateOperatorType options:NSDiacriticInsensitivePredicateOption];
                [eventsComparisionPredicates addObject:eventEqualToPredicate];

is working now!