3

I am trying to implement the user's search functionality and for which I am trying to Use NSPredicate but it's not working.

I am trying to use LIKE Query.

Here is the code I am using

NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(%@ CONTAINS[cd] %@) OR (%@ CONTAINS[cd] %@) AND %@ != %@",KEY_FirstName, sender.text,KEY_Lastname, sender.text,KEY_Id,[PFUser currentUser].objectId];
queryForUserSearch = [PFUser queryWithPredicate:userPredicate];

// I also tried this 
NSPredicate *userPredicate = [NSPredicate predicateWithFormat:@"(%@ = %@) OR (%@ = %@) AND %@ != %@",KEY_FirstName, sender.text,KEY_Lastname, sender.text,KEY_Id,[PFUser currentUser].objectId];
queryForUserSearch = [PFUser queryWithPredicate:userPredicate];

And I am getting belowed error

reason: 'Regex queries are not supported with [PFQuery queryWithClassName:predicate:]. Please try to structure your data so that you can use an equalTo or containedIn query.'

I also search for this but not worked for me.

Malav Soni
  • 2,739
  • 1
  • 23
  • 52

1 Answers1

1

First off, your object, this is how you set this up, an example:

Book.h

#import <Foundation/Foundation.h>

@interface Book : NSObject

@property (strong, nonatomic)NSString *bookID;
@property (strong, nonatomic)NSString *publishingYear;
@property (strong, nonatomic)NSString *author;
@property (strong, nonatomic)NSString *printHouse;
@property (strong, nonatomic)NSString *title;
@property (strong, nonatomic)NSString *ISBN;

-(id)initWithBookObjectId:(NSString *)bookID
           publishingYear:(NSString *)publishingYear
                   author:(NSString *)author
               printHouse:(NSString *)printHouse
                    title:(NSString *)title
                     ISBN:(NSString *)ISBN;

- (id)initWithDictionary:(PFObject *)dic;

@end

Book.m

#import "Book.h"
#define NSHNullCheck(object) ([object isKindOfClass:[NSNull class]] ? nil : object)

@implementation Book
{
    NSDictionary * descriptionDict;
}

-(id)initWithBookObjectId:(NSString *)bookID
           publishingYear:(NSString *)publishingYear
                   author:(NSString *)author
               printHouse:(NSString *)printHouse
                    title:(NSString *)title
                     ISBN:(NSString *)ISBN;

{
    self = [super init];
    if (self) {
        _bookID = bookID;
        _publishingYear = publishingYear;
        _author = author;
        _printHouse = printHouse;
        _title = title;
        _ISBN = ISBN;}
    return self;
}

- (id)initWithDictionary:(PFObject *)dic
{
    self = [self initWithBookObjectId:dic.objectId
                       publishingYear:NSHNullCheck([dic  valueForKey:@"publishingYear"])
                               author:NSHNullCheck([dic  valueForKey:@"author"])
                           printHouse:NSHNullCheck([dic  valueForKey:@"printHouse"])
                                title:NSHNullCheck([dic  valueForKey:@"title"])
                                 ISBN:NSHNullCheck([dic  valueForKey:@"ISBN"])];


    descriptionDict = @{ @"sessionObjectId":_bookID,
                         @"teacherAge":_publishingYear,
                         @"teacherEmail":_author,
                         @"teacherFacebookuniquekey":_printHouse,
                         @"teacherFirstname":_title,
                         @"teacherGender":_ISBN};
    return self;
}

- (id)init
{
    self = [self initWithBookObjectId:nil
                       publishingYear:nil
                               author:nil
                           printHouse:nil
                                title:nil
                                ISBN:nil];
    return self;
}

- (NSString *)description
{
    return descriptionDict.description;
}

@end

Storing data in object Model: books is an array that holds your "book objects" The following snippet of code goes in whereever you pull your data from the network with a query from Parse.

for (PFObject *object in objects) { //"objects" here is the NSArrray returned from the parse query!
    Book *book = [[Book alloc] initWithBookObjectId:object.objectId];
    book.publishingYear = object[@"publishingYear"];
    book.author = object[@"author"];
    book.printHouse = object[@"printHouse"];
    book.title = object[@"title"];
    book.ISBN = object[@"isbn"];
    [self.books addObject:book];
}
if ([self.searchTerm isEqualToString:@""]) {
    self.filteredBooksArray = self.books;
} else {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.title contains[c] %@",self.searchTerm];
    self.filteredBooksArray = [NSMutableArray arrayWithArray:[self.books filteredArrayUsingPredicate:predicate]];
}
[self.booksTable reloadData];

So, this is how you do search with PFObjects, you first need to extract the data, save this data inside an NSObject subclass (a data object model) and then use regex predicates as you would on any object model with a search function in IOS.

There's this method:

PFQuery *query = [PFQuery queryWithClassName:@"Post"]
[query whereKey:@"hashtags" containsAllObjectsInArray:@[@"#parse", @"#ftw"]];
NSArray *parseFTWPosts = [query findObjects];

and then this method:

/ Using PFQuery
 [query whereKey:@"playerName" notEqualTo:@"Michael Yabuti"];
 [query whereKey:@"playerAge" greaterThan:@18];

 // Using NSPredicate
 NSPredicate *predicate = [NSPredicate predicateWithFormat: @"playerName != 'Michael Yabuti' AND playerAge > 18"];
 PFQuery *query = [PFQuery queryWithClassName:@"GameScore" predicate:predicate];

and then this snippet:

Specifying Constraints with NSPredicate

To get the most out of PFQuery we recommend using its methods listed below to add constraints. However, if you prefer using NSPredicate, a subset of the constraints can be specified by providing an NSPredicate when creating your PFQuery.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"playerName = 'Dan Stemkosk'"];
PFQuery *query = [PFQuery queryWithClassName:@"GameScore" predicate:predicate];

let predicate = NSPredicate(format: "playerName = 'Dan Stemkosk'")
var query = PFQuery(className: "GameScore", predicate: predicate)

These features are supported:

    Simple comparisons such as =, !=, <, >, <=, >=, and BETWEEN with a key and a constant.
    Containment predicates, such as x IN {1, 2, 3}.
    Key-existence predicates, such as x IN SELF.
    BEGINSWITH expressions.
    Compound predicates with AND, OR, and NOT.
    Sub-queries with "key IN %@", subquery.

The following types of predicates are not supported:

    Aggregate operations, such as ANY, SOME, ALL, or NONE.
    Regular expressions, such as LIKE, MATCHES, CONTAINS, or ENDSWITH.
    Predicates comparing one key to another.
    Complex predicates with many ORed clauses.

and more here:

https://github.com/ParsePlatform/Docs/blob/master/en/ios/queries.mdown

Larry Pickles
  • 4,615
  • 2
  • 19
  • 36
  • I guess this is useful when you locally filter data What I want to do is get only that data from parse which satisfy the predicate conditions. – Malav Soni Aug 29 '15 at 07:42
  • Oh yeah, that's a no go, you can't do that with parse, you can only use their query methods and pull all the data with "whereKeyEquals" and such in the query stream – Larry Pickles Aug 29 '15 at 07:44
  • Parse provide the method [PFUser queryWithPredicate:userPredicate] so I guess there must be some way to use this. – Malav Soni Aug 29 '15 at 07:46
  • but, I'll post this as well, because this may help – Larry Pickles Aug 29 '15 at 07:46
  • so, that's what you meant, yes, you can use predicates, but it's restricted, so I've posted the answer for local and server searching in multiple ways, basically the only ways that parse will allow' – Larry Pickles Aug 29 '15 at 07:51
  • so, it's explicity, that " Regular expressions, such as LIKE, MATCHES, CONTAINS, or ENDSWITH." is not supported with IOS, perhaps with cloud code, but I don't know off the top of my head – Larry Pickles Aug 29 '15 at 07:52
  • @Loxx, good examples that you wrote, thanks! Do you happen to know how to do the equivalent of "take(number)" and "skip(number)" in iOS, I searched but didn't find any example. thanks. – RainCast Oct 09 '16 at 02:44