On Mar 13, 2011, at 1:51 AM, Indragie Karunaratne wrote:

> Andreas,
> 
> That predicate syntax (and block predicates) won't work in my case because 
> I'm using them in a Core Data NSFetchRequest.
This is true only if you use a sqlite store - but this is also most likely ;)

If you were not using SQLite, this simple predicate should have worked with a 
fetch request:
NSPredicate* pred = [NSPredicate predicateWithFormat:@"ALL %@ IN {attr0, 
attr1}", terms];

where terms is an array (or better a set) of strings, and attr0 and attr1 are 
key paths for attributes of the managed object. Here, the values for the 
attributes for each candidate of the managed objects are used in the predicate.

The predicate becomes true only if all search terms are found in any of the 
values of the attributes.

You may have meant it the other way around, then the predicate would become:
NSPredicate* pred = [NSPredicate predicateWithFormat:@"ALL {attr0, attr1} IN 
%@", terms];


Anyway, as you already found out, this predicate would not work with a sqlite 
store type. The reason is, that a *fetch* predicate must be mapped to an 
equivalent sqlite query - which is not always possible.

The error isn't a parser error, though. It is actually an Invalid Argument 
Exception whose reason is "unsupported predicate" which is thrown when you try 
to *execute the fetch*. So, the task is to find another form of the predicate 
which will work with the sqlite store.



> I did, however, manage to solve this issue by using subpredicates:

This is fine, however I'm not completely confident that your compound predicate 
(below) actually expresses your original intent.
Consider, the prediacte
  All tems IN attributes
is equivalent to
  (term_0 IN attributes) AND (term_1 IN attributes) ...  AND (term_n IN 
attributes)

So the code for this would look like this:

NSMutableArray* subPredicates = [[NSMutableArray alloc] initWithCapacity:[terms 
count]];
for (NSString* term in terms) {
    NSPredicate* p = [NSPredicate predicateWithFormat:@"%@ IN {attr0, attr1}", 
term];
    [subPredicates addObject:p];
}
NSPredicate* pred = [NSCompoundPredicate 
andPredicateWithSubpredicates:subPredicates];
[subPredicates release], subPredicates = nil;        
[fetchRequest setPredicate:pred];

 
Regards
Andreas


> 
>  NSPredicate *basePredicate = [NSPredicate predicateWithFormat:@"(name 
> CONTAINS[cd] $QUERY) OR (artist.name CONTAINS[cd] $QUERY)"];
>     NSMutableArray *andPredicates = [NSMutableArray array];
>     for (NSString *term in terms) {
>         NSDictionary *substitution = [NSDictionary 
> dictionaryWithObjectsAndKeys:term, @"QUERY", nil];
>         NSPredicate *andPredicate = [basePredicate 
> predicateWithSubstitutionVariables:substitution];
>         [andPredicates addObject:andPredicate];
>     }
>  NSPredicate *finalPredicate = [NSCompoundPredicate 
> andPredicateWithSubpredicates:andPredicates];
> 
> On 2011-03-12, at 6:17 AM, Andreas Grosam wrote:
> 
>> 
>> On Mar 12, 2011, at 3:36 AM, Indragie Karunaratne wrote:
>> 
>>> I have an NSManagedObject that has the following string attributes:
>>> 
>>> artist, albumArtist, composer, comments, and lyrics
>>> 
>>> I need to write an NSPredicate that will take an array of search terms, and 
>>> check if all of the above string attributes COMBINED contains every term in 
>>> the search term array. I tried the following predicate format:
>>> 
>>> NSArray *searchTerms = [NSArray arrayWithObjects:@"testing", @"search", 
>>> nil];
>>> NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL %@ IN { 
>>> artist, albumArtist, composer, comments, lyrics }", searchTerms];
>>> 
>>> This triggered a parsing error and would not run. Is there any way I can do 
>>> this in an NSPredicate, aside from creating a "search string" attribute in 
>>> my data model containing a concatenated string of the above attributes?
>> 
>> 
>> You should not include the object where the predicate is run against into 
>> the parameters of the format string. Otherwise, you would get a constant 
>> expression, rather a predicate.
>> 
>> Furthermore, when specifying an embedded string-list you need to quote the 
>> string elements.
>> 
>> This should work then:
>> 
>> NSArray* terms = ...
>> NSPredicate* pred = [NSPredicate predicateWithFormat:@"ALL self IN 
>> {'artist', 'albumArtist', 'composer', 'comments'}"];
>> 
>> BOOL test = [pred evaluateWithObject:terms];
>> 
>> 
>> Note: you can use a ^block for the predicate as well.
>> 
>> 
>> Regards
>> Andreas_______________________________________________
>> 
>> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
>> 
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>> 
>> Help/Unsubscribe/Update your Subscription:
>> http://lists.apple.com/mailman/options/cocoa-dev/cocoadev%40indragie.com
>> 
>> This email sent to cocoa...@indragie.com
> 

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to