Modifying hitSource

Hi everyone,

I was able to fetch data from the algolia server using InstantSearch and now, I want to filter there some data and put the filtered data into another array. I have following example:

var filteredHitsInteractor= HitsInteractor<JSON>()
    
    for index in 0..<(hitsCollectionViewController.hitsSource?.numberOfHits())! - 1 {
        
        let challengeObject = Challenge(json:(hitsCollectionViewController.hitsSource?.hit(atIndex: index))!)
        
        let currentDate = Date()
        let beginningDate = DateUtilManager.convertStringToDate(dateString: challengeObject.beginningDate)
        let endingDate = DateUtilManager.convertStringToDate(dateString: challengeObject.endingDate)
        
        if (currentDate < endingDate && beginningDate < currentDate ) {
            var jsonArray = [JSON]()
            jsonArray.append((hitsCollectionViewController.hitsSource?.hit(atIndex: index))!)
            filteredHitsInteractor.getCurrentHits() = jsonArray // this doesn't work
        }
    }

However, this line doesn’t work:

        filteredHitsInteractor.getCurrentHits() = jsonArray // this doesn't work

Since, getCurrentHits provided unmutable result. What can I do there?

Best regards,
Kaan

Hi Kaan,

HitsInteractor is designed to be externally immutable as it handles pagination logic and an outside interference can corrupt it and lead to unexpected behaviour. It only can be updated by Searcher.

So, you only can store your manually filtered result in an external array.
A better approach would be to implement filtering by date using FilterState, connected to your searcher.

Hi Vladislav,

thanks for the reply. I can try that. But let’s say, I have the filtered data in a separate array. How can I assign this array as a datasource to my hitsCollectionView?

ok, I have following code:

    let filterState = FilterState()
  
    let filterGroups =  filterState.toFilterGroups()
    
    // convert list of filter groups to Algolia filter SQL syntax
    let filters = FilterGroupConverter().sql(filterGroups)

    let currentDate = Date()
    let dateTimeStamp = Int(currentDate.timeIntervalSince1970)
    
    let query = Query(query: "query")
    query.filters = "beginningTimeStamp < \(dateTimeStamp) && \(dateTimeStamp) < endingTimeStamp"
    
    // set filters to Query
    query.filters = filters
    
    singleIndexSearcher.query = "\(query)"
    singleIndexSearcher.search()

But I get no results. What is wrong above? Thanks!

Hi Kaan,

You can implement your own wrapper for this filtered data conforming to UICollectionViewDataSource protocol and then assign it as a datasource to your CollectionView.

In your code snippet you use FilterState in the wrong way. Please familiarise yourself with section about filtering in Getting Started Guide and numeric range filtering guide. It should help with our use-case.

Hi Vladislav,

thanks for the reply. I was able to manage the some parts of the filtering by using following code:

let currentDate = Date()
let dateTimeStamp = Int(currentDate.timeIntervalSince1970)

    let query = Query()
    query.numericFilters = ["endingTimeStamp < \(dateTimeStamp)"]
    let index: Index = Client(appID: "XXX", apiKey: "XXX").index(withName: "challenges")
           
    singleIndexSearcher.indexQueryState = .init(index: index, query: query)
    singleIndexSearcher.search()

This works. However, if I combine a search expression with an AND operator, then it doesn’t work somehow. I get all the results back and not the ones which are filtered.

query.filters = “beginningTimeStamp < (dateTimeStamp) AND endingTimeStamp > (dateTimeStamp)”

Do you know what I have to do here?

Hi Kaan,

In your example you use the correct filtering syntax, but there is a missing backslash before your (dateTimeStamp) declaration, so the value of dateTimeStamp variable is not injected into you string.

Hi Vladislav,

you are right. I forgot that backslash but it still doesn’t give me the expected results. I retrieve everything. By checking manually, this should not be the case though.

Best regards,
Kaan

Hi Vladislav,

could you answer my latest reply, please?

Hi Kaan,

Actually there was a bug in the InstantSearch Core library which made impossible to use timestamps as numeric filters. It is fixed since version 6.5.2. Feel free to try it.

1 Like

Thanks Vladislav. That fixed it indeed =) Sorry for the late reply