Swift iOS -How to decode a nested query

To run Algolia searches from inside my iOS app I initially had my db structured like

@sneakers
      @000_aaa // postId
          -address: "mmm"
          -city: ...
          -state: ...

And inside the app

var refIndex: InstantSearchClient.Index!
let query = Query()

override func viewDidLoad() {
        super.viewDidLoad()

    let apiClient = Client(appID: "...", apiKey: "...publicKey...")
    refIndex = apiClient.index(withName: "sneakers")
    query.restrictSearchableAttributes = ["address"]
    query.attributesToRetrieve = ["address", "city", "state"]
}

The searches worked perfectly, and the json results always contained the address, city, and country.

I now have my database like this:

@sneakers
      @000_aaa
           @account_info // this child is added, and the k/v are nested below it, but I can no longer parse them
               -address: "mmm"
               -city: ...
               -state: ...

And my app like this:

override func viewDidLoad() {
        super.viewDidLoad()

    // ...
    query.restrictSearchableAttributes = ["account_info.address"]
    query.attributesToRetrieve = ["address, "city", "state"]
}

But the returned search results are now empty, a hit was returned but the json doesn’t have the address key and value nor the city and country. I added a break point and it only has 2 values, objectID and _highlightResult

Screen Shot 2021-04-02 at 9.36.29 PM

Screenshots from inside the Algolia console:

Screen Shot 2021-04-02 at 8.33.59 PM

My data model:

final class Result {

    var address: String?
    var city: String?
    var state: String?

    init(json:[String:Any]) {

        if let address = json["address"] as? String {
            self.address = address
        }
        
        if let city = json["city"] as? String {
            self.city = city
        }
        
        if let country = json["country"] as? String {
            self.country = country
        }
    }
}

Search:

query.query = searchController.searchBar.text

refIndex.search(query, completionHandler: { (data, error) in

    // the issue is occurring here
    guard let hits = data!["hits"] as? [[String: AnyObject]] else { return }
    guard let nbPages = data!["nbPages"] as? UInt else { return }

    var tmp = [Result]()
    for hit in hits {
        tmp.append(Result(json: hit))
    }

    self.dataSource = tmp
    self.tableView.reloadData()
})

After multiple attempts I had to do 3 things:

1- In the Algolia dashboard.console I had to set the Searchable Attributes and Retrievable Attributes to the same attributes as what’s in (2-)

2- when setting query.attributesToRetrieve I had to prefix all of the values that I wanted to retrieve with account_info. like this:

override func viewDidLoad() {
        super.viewDidLoad()

    // ...
    query.restrictSearchableAttributes = ["account_info.address"]

    // account_info. is prefixed to all of the values inside the array
    query.attributesToRetrieve = ["account.info", "account_info.city", "account_info.country", "account_info.address"]
}

which resulted in my breakpoint data looking like this (look at the results of [1] key)

Screen Shot 2021-04-02 at 10.05.47 PM

3- when the search returned a result, I had to parse the json and search for the account_info key, then parse its value as a dictionary:

guard let hits = data!["hits"] as? [[String: Any]] else { return }

var tmp = [Result]()

for hit in hits {

    // this is where I parse for the account_info key, entry will be account_info
    if let entry = hit.keys.first(where: { $0.lowercased().contains("account_info") }) {

        if let dict = hit[entry] as? [String: Any] {

            tmp.append(Result(json: dict))
        }
    }
}

self.dataSource = tmp
self.tableView.reloadData()