Skip to content

Commit b860c25

Browse files
author
Clément Le Provost
committed
Add missing query parameters filters and numericFilters
The rationale for not implementing them was that they cannot be adequately typed. However, after investigation: - `numericFilters` has roughly the same complexity as `tagFilters` or `facetFilters`. Therefore using a JSON array type, like for those parameters, should be adequate (although suboptimal). - `filters` is designed to be a “SQL-like notation”, so I guess a raw string type is adequate. In the future, we may want to provide tools to build the filters more easily, but this will likely come in the form of “helpers”, as it is done in the Javascript client. Since the absence of typed properties for the missing parameters was confusing, I am adding them now.
1 parent feb1660 commit b860c25

File tree

3 files changed

+49
-16
lines changed

3 files changed

+49
-16
lines changed

Source/Query.swift

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,6 @@ import Foundation
3737
// of the untyped storage (i.e. serializing to and parsing from string
3838
// values).
3939
//
40-
// ## Unmapped parameters
41-
//
42-
// Some parameters are too complex and have no typed accessors. They are
43-
// documented in the class's description.
44-
//
4540
// # Bridgeability
4641
//
4742
// **This Swift client must be bridgeable to Objective-C.**
@@ -154,12 +149,6 @@ public func ==(lhs: LatLng, rhs: LatLng) -> Bool {
154149
/// 2. Using the low-level, untyped getter (`get()`) and setter (`set()`) or the subscript operator.
155150
/// Use this approach if the parameter you wish to set is not supported by this class.
156151
///
157-
/// The following parameters have no typed property because they are too complex. You can still access them using
158-
/// the low-level methods/subscript operator:
159-
///
160-
/// - `filters`
161-
/// - `numericFilters`
162-
///
163152
@objc public class Query : NSObject, NSCopying {
164153

165154
// MARK: - Low-level (untyped) parameters
@@ -533,8 +522,12 @@ public func ==(lhs: LatLng, rhs: LatLng) -> Bool {
533522

534523
// MARK: Numeric search parameters
535524

536-
// NOTE: `numericFilters` omitted because loosely typed (see implementation notes above).
537-
525+
/// Filter on numeric attributes.
526+
@objc public var numericFilters: [AnyObject]? {
527+
get { return Query.parseJSONArray(get("numericFilters")) }
528+
set { set("numericFilters", value: Query.buildJSONArray(newValue)) }
529+
}
530+
538531
// MARK: Category search parameters
539532

540533
/// Filter the query by a set of tags.
@@ -588,8 +581,25 @@ public func ==(lhs: LatLng, rhs: LatLng) -> Bool {
588581
}
589582

590583
// MARK: Unified filter parameter (SQL like)
591-
592-
// NOTE: `filters` omitted because loosely typed (see implementation notes above).
584+
585+
/// Filter the query with numeric, facet or/and tag filters.
586+
/// The syntax is a SQL like syntax, you can use the OR and AND keywords. The syntax for the underlying numeric,
587+
/// facet and tag filters is the same than in the other filters:
588+
///
589+
/// available=1 AND (category:Book OR NOT category:Ebook) AND publication_date: 1441745506 TO 1441755506
590+
/// AND inStock > 0 AND author:"John Doe"
591+
///
592+
/// The list of keywords is:
593+
///
594+
/// - `OR`: create a disjunctive filter between two filters.
595+
/// - `AND`: create a conjunctive filter between two filters.
596+
/// - `TO`: used to specify a range for a numeric filter.
597+
/// - `NOT`: used to negate a filter. The syntax with the `-` isn't allowed.
598+
///
599+
@objc public var filters: String? {
600+
get { return get("filters") }
601+
set { set("filters", value: newValue) }
602+
}
593603

594604
// MARK: Geo-search parameters
595605

Tests/IndexTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ class IndexTests: XCTestCase {
695695
} else {
696696
// Delete by query.
697697
let query = Query()
698-
query["numericFilters"] = "dummy < 1500"
698+
query.numericFilters = ["dummy < 1500"]
699699
self.index.deleteByQuery(query, completionHandler: { (content, error) -> Void in
700700
if error != nil {
701701
XCTFail(error!.localizedDescription)

Tests/QueryTests.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,4 +617,27 @@ class QueryTests: XCTestCase {
617617
let query2 = Query.parse(query1.build())
618618
XCTAssertEqual(query2.minimumAroundRadius, 1000)
619619
}
620+
621+
func test_numericFilters() {
622+
let VALUE: [AnyObject] = ["code=1", ["price:0 to 10", "price:1000 to 2000"]]
623+
let query1 = Query()
624+
XCTAssertNil(query1.numericFilters)
625+
query1.numericFilters = VALUE
626+
XCTAssertEqual(query1.numericFilters! as NSObject, VALUE as NSObject)
627+
XCTAssertEqual(query1["numericFilters"], "[\"code=1\",[\"price:0 to 10\",\"price:1000 to 2000\"]]")
628+
let query2 = Query.parse(query1.build())
629+
XCTAssertEqual(query2.numericFilters! as NSObject, VALUE as NSObject)
630+
}
631+
632+
func test_filters() {
633+
let VALUE = "available=1 AND (category:Book OR NOT category:Ebook) AND publication_date: 1441745506 TO 1441755506 AND inStock > 0 AND author:\"John Doe\""
634+
let query1 = Query()
635+
XCTAssertNil(query1.filters)
636+
query1.filters = VALUE
637+
XCTAssertEqual(query1.filters, VALUE)
638+
XCTAssertEqual(query1["filters"], VALUE)
639+
let query2 = Query.parse(query1.build())
640+
XCTAssertEqual(query2.filters, VALUE)
641+
}
642+
620643
}

0 commit comments

Comments
 (0)