diff --git a/Sources/MeiliSearch/Model/FacetStats.swift b/Sources/MeiliSearch/Model/FacetStats.swift new file mode 100644 index 00000000..08971668 --- /dev/null +++ b/Sources/MeiliSearch/Model/FacetStats.swift @@ -0,0 +1,14 @@ +import Foundation + +/** + `FacetStats` instance represents the minimum and maximum values received for a provided facet + */ +public struct FacetStats: Codable, Equatable { + // MARK: Properties + + /// The minimum value found in the given facet + public let min: Double + + /// The maximum value found in the given facet + public let max: Double +} diff --git a/Sources/MeiliSearch/Model/SearchResult.swift b/Sources/MeiliSearch/Model/SearchResult.swift index f14b6546..c1d92124 100644 --- a/Sources/MeiliSearch/Model/SearchResult.swift +++ b/Sources/MeiliSearch/Model/SearchResult.swift @@ -15,6 +15,9 @@ public class Searchable: Equatable, Codable where T: Codable, T: Equatable { /// Distribution of the given facets. public var facetDistribution: [String: [String: Int]]? + + /// Maximum & minimum stats of a numeric facet. + public var facetStats: [String: FacetStats]? /// Time, in milliseconds, to process the query. public var processingTimeMs: Int? @@ -25,6 +28,7 @@ public class Searchable: Equatable, Codable where T: Codable, T: Equatable { public enum CodingKeys: String, CodingKey { case hits case facetDistribution + case facetStats case processingTimeMs case query } diff --git a/Tests/MeiliSearchIntegrationTests/SearchTests.swift b/Tests/MeiliSearchIntegrationTests/SearchTests.swift index da211ee8..7cbe26e4 100644 --- a/Tests/MeiliSearchIntegrationTests/SearchTests.swift +++ b/Tests/MeiliSearchIntegrationTests/SearchTests.swift @@ -86,6 +86,7 @@ class SearchTests: XCTestCase { XCTAssertEqual(result.query, query) XCTAssertEqual(result.limit, 20) XCTAssertEqual(result.hits.count, 1) + XCTAssertNil(result.facetStats) if response.hits.count > 0 { XCTAssertEqual("A Moreninha", response.hits[0].title) XCTAssertNil(response.hits[0].formatted) @@ -936,6 +937,7 @@ class SearchTests: XCTestCase { XCTAssertEqual(facetDistribution["genres"]?.keys.sorted(), expected["genres"]?.keys.sorted()) XCTAssertEqual(facetDistribution["genres"]?.values.sorted(), expected["genres"]?.values.sorted()) + XCTAssertEqual(documents.facetStats, [:]) expectation.fulfill() case .failure(let error): @@ -993,6 +995,49 @@ class SearchTests: XCTestCase { } self.wait(for: [expectation], timeout: 2.0) } + + // MARK: Facet stats + + func testSearchFacetStats() { + let expectation = XCTestExpectation(description: "Search for Books using facets") + + configureFilters { result in + switch result { + case .success: + typealias MeiliResult = Result, Swift.Error> + let limit = 5 + let query = "A" + let facets = ["id"] + let parameters = SearchParameters(query: query, limit: limit, facets: facets) + + self.index.search(parameters) { (result: MeiliResult) in + switch result { + case .success(let documents): + let result = documents as! SearchResult + + XCTAssertEqual(documents.query, query) + XCTAssertEqual(result.limit, limit) + XCTAssertEqual(documents.hits.count, limit) + + XCTAssertEqual(documents.facetStats?["id"]?.min, 1) + XCTAssertEqual(documents.facetStats?["id"]?.max, 1844) + + expectation.fulfill() + case .failure(let error): + dump(error) + XCTFail("Failed to search with testSearchFacetStats") + expectation.fulfill() + } + } + case .failure(let error): + dump(error) + XCTFail("Could not update settings") + expectation.fulfill() + } + } + + self.wait(for: [expectation], timeout: 2.0) + } } // swiftlint:enable force_unwrapping // swiftlint:enable force_try