Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSPredicate: Combine CONTAINS with IN

I have a set of users in CoreData and an search field in my application. User has the properties firstname and name.

Currently I have a predicate like "user.name CONTAINS[c] %@ OR user.firstname CONTAINS[c] %@ "

This works until the user types a full name like "john smith". Even if he types "john sm" the John Smith-Object should be found.

What is the predicate to combine an array (IN) of search terms with CONTAINS?

like image 646
netshark1000 Avatar asked Nov 20 '12 18:11

netshark1000


3 Answers

Swift 4 Update:

let firstName = NSPredicate(format: "firstName CONTAINS[c] %@", searchText)
let lastName = NSPredicate(format: "lastName CONTAINS[c] %@", searchText)

let orCompoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: 
[firstNamePredicate,lastNamePredicate]

Use the orCompoundPredicate while fetching data.

like image 73
Sanket Ray Avatar answered Oct 01 '22 21:10

Sanket Ray


I don't think that you can combine "IN" with "CONTAINS" in a predicate. But you could split the search string into words, and create a "compound predicate":

NSString *searchString = @"John  Sm ";
NSArray *words = [searchString componentsSeparatedByString:@" "];
NSMutableArray *predicateList = [NSMutableArray array];
for (NSString *word in words) {
    if ([word length] > 0) {
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"user.name CONTAINS[c] %@ OR user.firstname CONTAINS[c] %@", word, word];
        [predicateList addObject:pred];
    }
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateList];
NSLog(@"%@", predicate);

This example produces the predicate

(user.name CONTAINS[c] "John" OR user.firstname CONTAINS[c] "John") AND
(user.name CONTAINS[c] "Sm" OR user.firstname CONTAINS[c] "Sm")

which would match "John Smith", but not "John Miller".

like image 39
Martin R Avatar answered Oct 01 '22 19:10

Martin R


2.5 years later I can answer my question with a bit more complex example in swift:

var predicateList = [NSPredicate]()

let words = filterText.componentsSeparatedByString(" ")

for word in words{

     if count(word)==0{
           continue
     }

     let firstNamePredicate = NSPredicate(format: "firstName contains[c] %@", word)
     let lastNamePredicate = NSPredicate(format: "lastName contains[c] %@", word)
     let departmentPredicate = NSPredicate(format: "department contains[c] %@", word)
     let jobTitlePredicate = NSPredicate(format: "jobTitle contains[c] %@", word)

     let orCompoundPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [firstNamePredicate, lastNamePredicate,departmentPredicate,jobTitlePredicate])

     predicateList.append(orCompoundPredicate)
}

request.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicateList)
like image 44
netshark1000 Avatar answered Oct 01 '22 20:10

netshark1000