algolia / instantsearch-ios

⚑️ A library of widgets and helpers to build instant-search applications on iOS.
https://www.algolia.com/doc/guides/building-search-ui/what-is-instantsearch/ios/
Apache License 2.0
595 stars 58 forks source link

Incorrect number of hits on HitsInteractor when using pagination (infinitescroll) #260

Closed steffidg closed 1 year ago

steffidg commented 1 year ago

Describe the bug πŸ› With infinitescroll the HitsInteractor returns an incorrect number of hits after query is changed with hits less than the previous one.

To Reproduce πŸ” Steps to reproduce the behavior:

Pre-req: On example project, configure Paging Single Index to support applying of filter that will return less hits than the default

  1. Go to Paging Single Index
  2. Scroll down to at least 3 pages or more (roughly you'll be at numberOfHits=80 and above)
  3. Apply filter (this filter should have a result that is less than the number of hits pre-filter)
  4. See error.

Expected behavior πŸ’­ HitsInteractor.numberOfHits should return the numbers from step 3 but it returns step 2 numbers.

Here's a demo video: https://user-images.githubusercontent.com/81630747/195762256-fada5382-119f-4eb6-ba82-4fdf141a1080.mov Note: On the demo, I'm using our own indices.

Environment:

Additional context

  if hitsSource.numberOfHits() > stats.totalHitsCount {
      return stats.totalHitsCount
  }
   return hitsSource.numberOfHits()
VladislavFitz commented 1 year ago

Hi @steffidg , Could you make sure that the HitsInteractor instance is connected to the FilterState using the connectFilterState method in your example? This connection ensures resetting the cached hits stored in the HitsInteractor whenever the FilterState changed.

steffidg commented 1 year ago

Hi @VladislavFitz Tried it but unfortunately I'm still getting the incorrect number of hits.

class EcommerceDemoController {

    let searcher: HitsSearcher
    let hitsInteractor: HitsInteractor<Hit<StoreItem>>
    let searchBoxConnector: SearchBoxConnector
    let statsConnector: StatsConnector
    let loadingConnector: LoadingConnector
    let filterState: FilterState = .init()

    init(searchTriggeringMode: SearchTriggeringMode = .searchAsYouType) {
        let client = SearchClient(appID: "appid", apiKey: "apikey")
        Logger.minSeverityLevel = .trace
        searcher = .init(client: client, indexName: "indexname")
        searcher.connectFilterState(filterState)

// Connectors
       searchBoxConnector = .init(searcher: searcher, searchTriggeringMode: searchTriggeringMode)
        statsConnector = .init(searcher: searcher)
        loadingConnector = .init(searcher: searcher)

// Interactor
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        hitsInteractor = .init(jsonDecoder: decoder)
        hitsInteractor.connectFilterState(filterState)
        hitsInteractor.connectSearcher(searcher)
    }

// Called on tap of apply filters button    
    func applyFilters() {
        filterState[and: "conjunctiveGroup"].add(Filter.Facet(attribute: "price.range", stringValue: "β‚±500-β‚±1,500"))
        filterState[and: "conjunctiveGroup"].add(Filter.Facet(attribute: "stock.stock_label", stringValue: "In Stock"))
        filterState[and: "conjunctiveGroup"].add(Filter.Facet.init(attribute: "reviews.average_rating", stringValue: "5"))
        searcher.search()
    }
}

Screen Shot 2022-10-24 at 10 05 18 AM

VladislavFitz commented 1 year ago

Hi @steffidg, I slightly modified the demo application to reproduce the issue you reported. You can find it in the branch hits-count-issue branch. Please try it by launching the PagingSingleIndex target of the Examples application. I logged the same data as you in your example and it works as expected.

steffidg commented 1 year ago

Hi @VladislavFitz Oh. I see! Yes it works fine now. Appreciate the help!