diff --git a/Parse/Internal/Query/PFQueryConstants.h b/Parse/Internal/Query/PFQueryConstants.h index 97c3cc5f0..c75301081 100644 --- a/Parse/Internal/Query/PFQueryConstants.h +++ b/Parse/Internal/Query/PFQueryConstants.h @@ -23,6 +23,7 @@ extern NSString *const PFQueryKeyNearSphere; extern NSString *const PFQueryKeyWithin; extern NSString *const PFQueryKeyGeoWithin; extern NSString *const PFQueryKeyGeoIntersects; +extern NSString *const PFQueryKeyText; extern NSString *const PFQueryKeyRegex; extern NSString *const PFQueryKeyExists; extern NSString *const PFQueryKeyInQuery; @@ -39,6 +40,8 @@ extern NSString *const PFQueryOptionKeyMaxDistance; extern NSString *const PFQueryOptionKeyBox; extern NSString *const PFQueryOptionKeyPolygon; extern NSString *const PFQueryOptionKeyPoint; +extern NSString *const PFQueryOptionKeySearch; +extern NSString *const PFQueryOptionKeyTerm; extern NSString *const PFQueryOptionKeyRegexOptions; NS_ASSUME_NONNULL_END diff --git a/Parse/Internal/Query/PFQueryConstants.m b/Parse/Internal/Query/PFQueryConstants.m index 9a9739dfa..df6af9b74 100644 --- a/Parse/Internal/Query/PFQueryConstants.m +++ b/Parse/Internal/Query/PFQueryConstants.m @@ -22,6 +22,7 @@ NSString *const PFQueryKeyGeoWithin = @"$geoWithin"; NSString *const PFQueryKeyGeoIntersects = @"$geoIntersects"; NSString *const PFQueryKeyRegex = @"$regex"; +NSString *const PFQueryKeyText = @"$text"; NSString *const PFQueryKeyExists = @"$exists"; NSString *const PFQueryKeyInQuery = @"$inQuery"; NSString *const PFQueryKeyNotInQuery = @"$notInQuery"; @@ -37,4 +38,6 @@ NSString *const PFQueryOptionKeyBox = @"$box"; NSString *const PFQueryOptionKeyPolygon = @"$polygon"; NSString *const PFQueryOptionKeyPoint = @"$point"; +NSString *const PFQueryOptionKeySearch = @"$search"; +NSString *const PFQueryOptionKeyTerm = @"$term"; NSString *const PFQueryOptionKeyRegexOptions = @"$options"; diff --git a/Parse/PFQuery.h b/Parse/PFQuery.h index dc929132e..681069d79 100644 --- a/Parse/PFQuery.h +++ b/Parse/PFQuery.h @@ -96,9 +96,9 @@ typedef void (^PFQueryArrayResultBlock)(NSArray *_Nullable obje /** Make the query include `PFObject`s that have a reference stored at the provided keys. - + @param keys The keys to load child `PFObject`s for. - + @return The same instance of `PFQuery` as the receiver. This allows method chaining. */ - (instancetype)includeKeys:(NSArray *)keys; @@ -196,6 +196,17 @@ typedef void (^PFQueryArrayResultBlock)(NSArray *_Nullable obje */ - (instancetype)whereKey:(NSString *)key notEqualTo:(id)object; +/** + Add a constraint for finding string values that contain a provided + string using Full Text Search + + @param key The key to be constrained. + @param text the substring that the value must contain. + + @return The same instance of `PFQuery` as the receiver. This allows method chaining. + */ +- (instancetype)whereKey:(NSString *)key matchesText:(NSString *)text; + /** Add a constraint to the query that requires a particular key's object to be contained in the provided array. diff --git a/Parse/PFQuery.m b/Parse/PFQuery.m index e360789f0..e3293ce09 100644 --- a/Parse/PFQuery.m +++ b/Parse/PFQuery.m @@ -311,6 +311,11 @@ - (instancetype)whereKey:(NSString *)key polygonContains:(PFGeoPoint *)point { return [self whereKey:key condition:PFQueryKeyGeoIntersects object:dictionary]; } +- (instancetype)whereKey:(NSString *)key matchesText:(NSString *)text { + NSDictionary *dictionary = @{ PFQueryOptionKeySearch : @{PFQueryOptionKeyTerm : text} }; + return [self whereKey:key condition:PFQueryKeyText object:dictionary]; +} + - (instancetype)whereKey:(NSString *)key matchesRegex:(NSString *)regex { return [self whereKey:key condition:PFQueryKeyRegex object:regex]; } diff --git a/Tests/Unit/QueryUnitTests.m b/Tests/Unit/QueryUnitTests.m index cd1154d10..25c060c85 100644 --- a/Tests/Unit/QueryUnitTests.m +++ b/Tests/Unit/QueryUnitTests.m @@ -419,7 +419,7 @@ - (void)testWhereKeyWithinPolygon { PFGeoPoint *geoPoint1 = [PFGeoPoint geoPointWithLatitude:10.0 longitude:20.0]; PFGeoPoint *geoPoint2 = [PFGeoPoint geoPointWithLatitude:20.0 longitude:30.0]; PFGeoPoint *geoPoint3 = [PFGeoPoint geoPointWithLatitude:30.0 longitude:40.0]; - + PFQuery *query = [PFQuery queryWithClassName:@"a"]; [query whereKey:@"yolo" withinPolygon:@[geoPoint1, geoPoint2, geoPoint3]]; XCTAssertEqualObjects(query.state.conditions, (@{ @"yolo" : @{@"$geoWithin" : @{@"$polygon" : @[ geoPoint1, geoPoint2, geoPoint3 ]}} })); @@ -427,12 +427,18 @@ - (void)testWhereKeyWithinPolygon { - (void)testWhereKeyPolygonContains { PFGeoPoint *geoPoint = [PFGeoPoint geoPointWithLatitude:10.0 longitude:20.0]; - + PFQuery *query = [PFQuery queryWithClassName:@"a"]; [query whereKey:@"yolo" polygonContains:geoPoint]; XCTAssertEqualObjects(query.state.conditions, (@{ @"yolo" : @{@"$geoIntersects" : @{@"$point" : geoPoint}} })); } +- (void)testWhereKeyMatchesText { + PFQuery *query = [PFQuery queryWithClassName:@"a"]; + [query whereKey:@"yolo" matchesText:@"yarr"]; + XCTAssertEqualObjects(query.state.conditions, (@{ @"yolo" : @{@"$text" : @{@"$search" : @{@"$term" : @"yarr"} }} })); +} + - (void)testWhereKeyMatchesRegex { PFQuery *query = [PFQuery queryWithClassName:@"a"]; [query whereKey:@"yolo" matchesRegex:@"yarr"];