Preventing multiple API hits when updating geolocation via browser API / query parsing

I am working on an vue app that

a) needs to parse the search query for keywords (city names, for ex. a query like “chinese food in London”) and then updates :around-lat-lng based on that.

b) Alternatively asynchronously gets the user’s position from the browser API and then sets :around-lat-lng.

My issue is that this generates more queries than there should be, which leads to flashing/changing of the results, performance issues as well as concurrency issues(I think - I’m getting some weird behaviors that I assume comes from multiple queries running asynchronously almost at the same time)

My question is how to best approach this:

a) parsing the query and updating position, then querying the Algolia API just one time. I’m not sure how to best intercept the query as it is being entered and also apply the same parsing logic for queries coming in from the URL via the routing/parseURL(). Currently I’m thinking I might need to roll my own modified ais-search-box. But unsure how to solve it for queries via parseURL().

b) again, when getting the position from the browser API, how to hold the query from being sent until that is done.

I’m using vue-instantsearch beta3 with custom routing and state mapping, a few facet filters and an ais-search-box.

Hi @loka,

a) parsing the query and updating position, then querying the Algolia API just one time. I’m not sure how to best intercept the query as it is being entered and also apply the same parsing logic for queries coming in from the URL via the routing/parseURL(). Currently I’m thinking I might need to roll my own modified ais-search-box. But unsure how to solve it for queries via parseURL().

You can extract the logic that parse the query and use it inside parseURL and ais-search-box. You have to customise the UI to be able to intercept the call to refine that triggers the network request. Two solutions are available to customise the UI: slots or the widget mixin.

b) again, when getting the position from the browser API, how to hold the query from being sent until that is done.

You want to prevent the initial request until the user allow the geolocation on the device? What is the condition that determine whether the search is ready to trigger the request? You cannot easily prevent the initial request with a prop. The only way is to create a custom searchClient. You can find a guide inside the repo.

Could you provide an example of your use case? It will help to better understand where the multiple requests come from. It can also be an issue inside the library. A use case like you have is not common. We provide a template to avoid you the boilerplate part.

Thanks! I got held up on some other issues but your advice definitely is helpful, I now know where to attack the problem :slight_smile:

If the multiple requests issue persists I’ll attempt to extract it into a codesandbox to reproduce it.

@samuel.vaillant Here is a codesandbox that shows (very simplified) my issue with multiple requests being sent.

Interesting bits:
@input="getCityFromQuery($event.currentTarget.value);refine($event.currentTarget.value);"/>

…triggers a function that will set the geo location (aroundLatLng) if the query contains “berk” (simplified for demo purposes)

If you enter this into the search box and watch the console, you will see the full query gets sent 3 times.

I guess this happens due to the aroundLatLng being immediately passed on and in turn triggering another refinement query. That would explain one additional query. But not sure about the third.

Also, when loading vue-instantsearch-v2-starter and then adding a “k” to the query, the k is removed again and the query is set to “ber” again.

I’m having trouble understanding where that might be coming from.

My use case, as explained earlier, is that users will search for ex. for “Doctors in London” expecting to find doctors in London only. What I am attempting to code here is a way to parse the query as it is entered, and if a major city is matched (contained within the query string), set the aroundLatLng to that city’s geographical center and only then send the algolia query.

Hi @loka,

Thanks a lot for the example, it was very helpful!

The fact that multiple request are triggered is expected at least for the first two. Like you said it’s because first it triggers the request for the aroundLatLng change and then the call to refine. The third one might be due to an issue that we have on our side.

I’ve opened an issue on GitHub.

Hi @samuel.vaillant,

Now I’m working around the issues I’m having with ais-configure by manually injecting aroundLatLng into “requests” in searchClient->async search.

searchClient: {
  async search (requests) {
    requests[0].params.aroundLatLng = latLngVariable;
    return algoliaClient.search(requests);
  }
}

That works quite well, except for the fact that now a new search isn’t triggered once my latLng value arrives from the browserAPI.

Any pointers how I can manually trigger the search refinment from within a vue instance method?

Thanks

Hi @loka,

You can apply the same strategy than what we have inside the guide about refreshing the cache. You’ll have access to the helper from the render function. You can create a function search that triggers a new search with helper.search(). Here is an example that implement this.

Hope that helps.

1 Like

That worked, thanks!

@samuel.vaillant

I’ve implemented this similar to the example you sent at Vue InstantSearch - Custom connector with search - CodeSandbox

But I just noticed that when I use helper.search() that no createURL() is triggered, meaning my url is not being updated (I write the URL based on the geolocation). Any idea how to do this?

Thanks!

Hi @loka,

It looks like the link you sent it’s the exact same Sandbox that the one I’ve created. Note that the one I’ve created does not have the routing option enabled. You have to enable it to sync the URL. If the issue persists please provide a Sandbox with an example of the issue.

Hope that helps.