algolia / algolia/algoliasearch-client-go
How to use BrowseObjects with v4
- Dominant language
- Go
- Stars
- 200
- Forks
- 60
- PR merge metrics
- No merged PRs in 30d
Description
It's not the first time I'm encountering this issue, but today, I thought I'd report it before the consequences spread in my project too much.
So how do you browse for records with v4? I think the best practice is to use [this high-level helper](https://www.algolia.com/doc/libraries/go/v4/helpers/#browse-for-records). Otherwise, you'd be doing [plumbing with the API using client.Browse()](https://www.algolia.com/doc/rest-api/search/#tag/Search/operation/browse)
The docs say:
> This helper function iterates over the paginated API response from the [Browse](https://www.algolia.com/doc/rest-api/search/#tag/Search/operation/browse) API operation and lets you run an aggregator function on every iteration.
## Documentation issue
The first issue is a documentation issue: how do you pass the aggregator function?
👉 you have to pass it using `opts`, and the option you pass can be `search.WithAggregator`, as indicated here: https://github.com/algolia/algoliasearch-client-go/blob/919ba1dc3465964fa6017f02454bf3737a341f03/algolia/search/api_search.go#L9030
## First DX issue
The second issue is a DX issue: the signature of the function you pass to `search.WithAggregator` is `func(any, error)`: https://github.com/algolia/algoliasearch-client-go/blob/919ba1dc3465964fa6017f02454bf3737a341f03/algolia/search/api_search.go#L8730
There is no guarantee about the response you are going to get. I would have expected `func(*search.BrowseResponse, error)` instead.
I believe that's because the `WithAggregator` helper can be used with more than just `BrowseObjects`, which makes sense.
To work this around, I've been forced to write my own helper, it goes like this:
```golang
package algoliahelpers
import (
"fmt"
"github.com/algolia/algoliasearch-client-go/v4/algolia/search"
)
type aggregator func(response *search.BrowseResponse)
func WrapAggregator(
aggregatorFunc aggregator,
) func(response any, errorResponse error) {
return func(response any, errorResponse error) {
if errorResponse != nil {
panic(errorResponse)
}
res, ok := response.(*search.BrowseResponse)
if !ok {
panic(fmt.Errorf("%w, got %T", ErrUnexpectedResponseType, response))
}
aggregatorFunc(res)
}
}
```
I have yet to figure out how to avoid these calls to `panic`
## Second issue
Even with that first DX issue addressed, another big DX issue remains: in v3, using browse meant you could obtain an iterator and not think about responses: they were completely abstracted. Now, the abstraction leaks, and to use this, you have to deal with responses, when before you dealt with hits directly. This feels like a big regression, to be honest.
## Third issue
As you can see above, there is not much room for simple error handing. It would have been nice to be able to return an `error` from the aggregator, causing the program to halt cleanly in case of error.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with algolia/search/api_search.go, especially the BrowseObjects and WithAggregator definitions linked in the issue, and compare them with the v4 browse documentation and client.Browse(). Done means the documented aggregator usage is clear and the browse API addresses the reported response-handling, iterator, and error-propagation concerns.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, developer-experience
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100