Open brunoocasali opened 1 year ago
@brunoocasali how do other compiler safe languages handle this API?
It's proving exceptionally difficult to have a method which expects an array of generics with different document types.
The best I've got (code below) is using message packs which syntaxically to the user looks nice but I'm unable to figure out how to zip up the pack of expected document types to an array of data from the API. I think this is because the feature is so new in Swift it lacks things like message pack iteration.
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) func multiSearch( _ searchParameters: [MultiSearchParameters] ) async throws -> (repeat Searchable ) { let data: Data do { var jsonBuilder = [[String: Any]]() for searchParameter in searchParameters { let jsonData = try JSONEncoder().encode(searchParameter.parameters) var jsonObject = try JSONSerialization.jsonObject(with: jsonData) as! [String: Any] jsonObject["indexUid"] = searchParameter.indexUid jsonBuilder.append(jsonObject) } data = try JSONSerialization.data(withJSONObject: [ "queries": jsonBuilder ]) } catch { throw MeiliSearch.Error.invalidJSON } return try await withCheckedThrowingContinuation { continuation in self.request.post(api: "/multi-search", data) { result in switch result { case .success(let data): do { let resultHolder = try JSONSerialization.jsonObject(with: data) as! [String: [Any]] let results: [Data] = try resultHolder["results"]!.map { try JSONSerialization.data(withJSONObject: $0) } print(results) // An array of JSON objects in Data form, ready for decoding. // ... magic? } catch { continuation.resume(throwing: error) } case .failure(let failure): continuation.resume(throwing: failure) } } } } Usage: let params: [MultiSearchParameters] = [ .init(indexUid: "indexA", parameters: .query("b")), .init(indexUid: "indexB", parameters: .init(query: "b", limit: 5)) ] let results: (Searchable , Searchable ) = try await search.multiSearch(params) print(results.0.hits.first?.document.id)
The simple solution would be to return an array of undecoded types. So the usage would look like:
let params: [MultiSearchParameters] = [
.init(indexUid: "indexA", parameters: .query("b")),
.init(indexUid: "indexB", parameters: .init(query: "b", limit: 5))
]
let results = try await search.multiSearch(params)
// notice the new `.decode()` function to move from the undecoded type to something they can use.
// this helps the compiler to know what the type is though simplifying the solution.
let firstResult: Searchable<Movie> = results[0].decode()
let secondResult: Searchable<Animal> = results[1].decode()
This feels like an okay compromise. The API is still pretty clean and clear what's happening.
It does lose the safety though where a user could do results[2].decode()
and crash due to there not being that many searches. The first solution wouldn't allow this.
This will be an issue to be accomplished here indeed.
I guess maybe you could take inspiration of those SDKS: Java (proposal), Rust and C#
Does it helps?
Unfortunately not, none of the three solutions above appear to demonstrate a compiler-safe and type-safe solution which allows for queries to different indexes with different document types.
The Rust one for example seems to show that all documents across the multiple queries must be of type Movie.
This would be an easy limitation for us to implement, but one which dramatically reduces the usefulness.
Separating the decode step (my approach above) adds one extra step to the execution but allows for mixed result responses. Think it's what we need to go for, for now, until more language capabilities are added (message packs)
Separating the decode step (my approach above) adds one extra step to the execution but allows for mixed result responses.
I guess it is the way to go in this case @Sherlouk 😢.
just to double check, multiSearch is not available in the Swift SDK?
Not at this time, we've yet to identify a completely compile/type safe solution which works in Swift.
⚠️ This issue is generated, it means the examples and the namings do not necessarily correspond to the language of this repository. Also, if you are a maintainer, feel free to add any clarification and instruction about this issue.
Sorry if this is already partially/completely implemented, feel free to let me know about the state of this issue in the repo.
Related to https://github.com/meilisearch/integration-guides/issues/251
Related to:
Create a new client method called
multiSearch
/multi_search
, which will requestPOST /multi-search
with a body payload containing a structure similar to this:Each object is a simple search object sent in the
POST /indexes/:indexUid/search
request.Pay attention to the response, which will follow the order of the requests object and will look like this (note the new
indexUid
key in the response):TODO:
multiSearch
method