Search code examples
swiftuisearchbaralgoliauisearchcontrollerinstantsearch

algolia filter works in console but is not working in actual search results


So my goal is to be able to filter out the Algolia hits not only in the console, but in the actual displayed results as well. So I've been stuck with this issue for a month or so now. I am using the AlgoliaSearchClient API with Swift and the InstantSearch library as well. I've recently figured out how to filter the hits but they only reflect in the console.

Here is the function I use to do that:

extension SchoolTableViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
    let settings = Settings()

        .set(\.searchableAttributes, to: [.default("eventName")])
        .set(\.attributesForFaceting, to: [.filterOnly("schoolID")])
        .set(\.attributesToRetrieve, to: ["*"])

     searchResultsIndex.setSettings(settings) { (result) in
        if case .success( _) = result {
            self.getTheSchoolsID { (schoolID) in
                if let id = schoolID {
                    let query = Query().set(\.filters, to: "schoolID:\(id)")
                    
                    searchResultsIndex.search(query: query) { (result) in
                            if case .success(let response) = result {
                                print("\(response.hits)")
                        }
                    }
                }
            }
        }
    }
}

}

This works perfectly in the console, I can only see events from the current users schoolID. Now when I search, in the actual search bar, I can see events from every user. I was told by an Algolia team member to use this line of code below to have the filter applied in the actual search as well.

 getTheSchoolsID { (id) in
        if let id = id {
            self.searcher.indexQueryState.query.filters = "schoolID:\(id)"
            self.searcher.search()
        }
    }

I've double checked the id value by printing it, it is the exact same value as the one in the function above. I can't figure out why the searchBar doesn't filter out the hits on the screen, but it does it in the console. The Algolia team member said I didn't have to set settings again because it was already set in the other function.

Here is the whole function I use to configure the Algolia search :

func configureAlgoliaSearch() {
    
    getTheSchoolsID { (id) in
        if let id = id {
            self.searcher.indexQueryState.query.filters = "schoolID:\(id)"
            self.searcher.search()
        }
    }
    searchConnector.connect()
 
    navigationController?.navigationBar.prefersLargeTitles = false
    navigationItem.setHidesBackButton(true, animated: true)
    
    algoliaSearchController.searchResultsUpdater = self
    algoliaSearchController.searchBar.searchTextField.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    algoliaSearchController.obscuresBackgroundDuringPresentation = false
    algoliaSearchController.searchBar.placeholder = "Event Name"
    navigationItem.searchController = algoliaSearchController
    definesPresentationContext = true
}

Any suggestions?


Solution

  • Finally after a month of struggling, I came up with a solution that I should've came up with a long time ago. I decided to create an index for each user. This basically allows me to ditch the need to filter out the records.

    All I needed to do was declare a couple variables in the viewController where the SearchController is.

     public let client = SearchClient(appID: ApplicationID(rawValue: Keys.algoliaAppID), apiKey: APIKey(rawValue: Keys.algoliaApiKey))
    
     lazy var algoliaSearchController: UISearchController = .init(searchResultsController: hitsViewController)
    lazy var searchConnector: SingleIndexSearchConnector<NameOfEvent> = .init(searcher: searcher,searchController: algoliaSearchController, hitsController: hitsViewController)
    
    let hitsViewController: SchoolInstantiatedHitsTableViewController = .init()
    
    let searcher: SingleIndexSearcher = SingleIndexSearcher(appID: ApplicationID(rawValue: Keys.algoliaAppID), apiKey: APIKey(rawValue: Keys.searcherApiKey), indexName: IndexName(rawValue: Auth.auth().currentUser!.uid) )
    

    Along with this function:

    extension SchoolTableViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        
        let searchBar = searchController.searchBar.searchTextField.text
        let index2 = client.index(withName: IndexName(rawValue: Auth.auth().currentUser!.uid))
        let settings = Settings()
            
            .set(\.searchableAttributes, to: [.default("eventName")])
            .set(\.attributesToRetrieve, to: ["*"])
        
        index2.setSettings(settings) { (result) in
            if case .success(_) = result {
                let query = Query(searchBar)
                
                index2.search(query: query) { (result) in
                    if case .success(_ ) = result {
                        print("Success")
                    }
                }
            }
        }
        
        
    }
    

    }

    And of course configuring the actual searchBar itself:

    func configureAlgoliaSearch() {
    
        searchConnector.connect()
        searcher.search()
        algoliaSearchController.delegate = self
        algoliaSearchController.searchResultsUpdater = self
        algoliaSearchController.searchBar.searchTextField.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
        algoliaSearchController.obscuresBackgroundDuringPresentation = false
        algoliaSearchController.searchBar.placeholder = "Event Name"
        navigationItem.searchController = algoliaSearchController
        definesPresentationContext = true
        
    }
    

    Now with these functions, when I add, delete, or update, records, they all work uniquely to the index of the current user. Algolia's documentation was very confusing at first and asking questions on the forum is kinda like talking to a rock. Anyways, I hope this can help somebody out in the future.