algolia / algolia/algoliasearch-client-go

How to use BrowseObjects with v4

Open
#772 1 comment 1 reaction 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.