Skip to content

Commit 1d68308

Browse files
Merge #410
410: Add async overload for search API r=curquiza a=Sherlouk # Pull Request ⚠️ I've marked this as draft as it current works to provide an example of how we could add async/await support to the library. I am more than happy to expand this to **all** currently supported APIs. ## Related issue Relates to #332 (doesn't close as only adds support for one API) ## What does this PR do? - Adds an async/await override to an existing search API providing users with more choice. ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Thank you so much for contributing to Meilisearch! Co-authored-by: James Sherlock <[email protected]>
2 parents 33d66ff + 338faad commit 1d68308

File tree

4 files changed

+68
-18
lines changed

4 files changed

+68
-18
lines changed

README.md

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -149,24 +149,13 @@ With the `uid` of the task, you can check the status (`enqueued`, `canceled`, `p
149149
#### Basic Search <!-- omit in toc -->
150150

151151
```swift
152-
153-
let semaphore = DispatchSemaphore(value: 0)
154-
155-
// Typealias that represents the result from Meilisearch.
156-
typealias MeiliResult = Result<SearchResult<Movie>, Swift.Error>
157-
158-
// Call the function search and wait for the closure result.
159-
client.index("movies").search(SearchParameters( query: "philoudelphia" )) { (result: MeiliResult) in
160-
switch result {
161-
case .success(let searchResult):
162-
dump(searchResult)
163-
case .failure(let error):
164-
print(error.localizedDescription)
165-
}
166-
semaphore.signal()
152+
do {
153+
// Call the search function and wait for the result.
154+
let result: SearchResult<Movie> = try await client.index("movies").search(SearchParameters(query: "philoudelphia"))
155+
dump(result)
156+
} catch {
157+
print(error.localizedDescription)
167158
}
168-
semaphore.wait()
169-
170159
```
171160

172161
Output:
@@ -191,6 +180,8 @@ Output:
191180

192181
Since Meilisearch is typo-tolerant, the movie `philadelphia` is a valid search response to `philoudelphia`.
193182

183+
> Note: All package APIs support closure-based results for backwards compatibility. Newer async/await variants are being added under [issue 332](https://github.com/meilisearch/meilisearch-swift/issues/332).
184+
194185
## 🤖 Compatibility with Meilisearch
195186

196187
This package guarantees compatibility with [version v1.x of Meilisearch](https://github.com/meilisearch/meilisearch/releases/latest), but some features may not be present. Please check the [issues](https://github.com/meilisearch/meilisearch-swift/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22+label%3Aenhancement) for more info.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import Foundation
2+
3+
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
4+
extension Indexes {
5+
/**
6+
Search in the index.
7+
8+
- Parameter searchParameters: Options on search.
9+
- Throws: Error if a failure occurred.
10+
- Returns: On completion if the request was successful a `Searchable<T>` instance is returned containing the values.
11+
*/
12+
public func search<T: Codable & Equatable>(_ searchParameters: SearchParameters) async throws -> Searchable<T> {
13+
try await withCheckedThrowingContinuation { continuation in
14+
self.search.search(self.uid, searchParameters) { result in
15+
continuation.resume(with: result)
16+
}
17+
}
18+
}
19+
}

Sources/MeiliSearch/Indexes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public struct Indexes {
2626
private let documents: Documents
2727

2828
// Search methods
29-
private let search: Search
29+
internal let search: Search
3030

3131
// Settings methods
3232
private let settings: Settings

Tests/MeiliSearchUnitTests/SearchTests.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,46 @@ class SearchTests: XCTestCase {
8080

8181
self.wait(for: [expectation], timeout: TESTS_TIME_OUT)
8282
}
83+
84+
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
85+
func testSearchForBotmanMovieAsync() async throws {
86+
let jsonString = """
87+
{
88+
"hits": [
89+
{
90+
"id": 29751,
91+
"title": "Batman Unmasked: The Psychology of the Dark Knight",
92+
"poster": "https://image.tmdb.org/t/p/w1280/jjHu128XLARc2k4cJrblAvZe0HE.jpg",
93+
"overview": "Delve into the world of Batman and the vigilante justice tha",
94+
"release_date": "2020-04-04T19:59:49.259572Z"
95+
},
96+
{
97+
"id": 471474,
98+
"title": "Batman: Gotham by Gaslight",
99+
"poster": "https://image.tmdb.org/t/p/w1280/7souLi5zqQCnpZVghaXv0Wowi0y.jpg",
100+
"overview": "ve Victorian Age Gotham City, Batman begins his war on crime",
101+
"release_date": "2020-04-04T19:59:49.259572Z"
102+
}
103+
],
104+
"offset": 0,
105+
"limit": 20,
106+
"processingTimeMs": 2,
107+
"estimatedTotalHits": 2,
108+
"query": "botman"
109+
}
110+
"""
111+
112+
// Prepare the mock server
113+
let data = jsonString.data(using: .utf8)!
114+
let stubSearchResult: Searchable<Movie> = try! Constants.customJSONDecoder.decode(Searchable<Movie>.self, from: data)
115+
session.pushData(jsonString)
116+
117+
// Start the test with the mocked server
118+
let searchParameters = SearchParameters.query("botman")
119+
120+
let searchResult: Searchable<Movie> = try await self.index.search(searchParameters)
121+
XCTAssertEqual(stubSearchResult, searchResult)
122+
}
83123

84124
func testSearchForBotmanMovieFacets() {
85125
let jsonString = """

0 commit comments

Comments
 (0)