Closed vamsikrishnasurathi closed 6 years ago
Hi @vamsikrishnasurathi,
Thanks for submitting this issue!
Can you please post the error stack that you are getting when you crash in index.search
? That will help me better assist you.
No not fixed still now I am new to algolia unable to implement and the error thrown was unexpectedly found nil while wrapping optional value
and here when it reached to index.search
line it's getting crashed and here appId ,api key and indices has been passed correctly and in order to filter the selected category id array has been passed but unable to display the data which has been passed from selected id @spinach
I don't know how you intitialised index
as it's not shown in the code snippet. It might be nil, hence the crash.
If you want your code to run, just try to replace index.search
with InstantSearch.shared.searcher.index
@vamsikrishnasurathi
I declared index as var index : Index! and here index is sub class of algolia search client and later I tried by changing code as you said but the filtered data has not been displayed @spinach
It's very hard to know what is the issue without having the whole code and putting breakpoints and see what is happening at each step.
Can you clarify what values you are expecting to see and what values you are actually seeing?
Here is my code and in this search i had implemented by watching tutorials successfully but here i need to filter the results to display sorted results
func collectionViewLoadData() {
if (self.appId != nil && self.apiKEY != nil && self.Indices != nil) {
InstantSearch.shared.configure(appID: "\(self.appId!)", apiKey: "\(self.apiKEY!)", index: "\(self.Indices!)en_products")
if receivedText != nil {
print(String(describing: receivedText!))
InstantSearch.shared.searchBar(searchBar, textDidChange: receivedText!)
}
// print(facetsArray)
// print(categoriesArray)
let query = Query()
query.facets = facetsArray
query.facetFilters = categoriesArray
InstantSearch.shared.searcher.index.search(query, requestOptions: nil, completionHandler: { (res, err) in
print(res)
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
})
hitsCollectionViews = [self.listCollectionView]
ActivityIndicator.stopAnimating()
}
}
open override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath,
containing hit: [String : Any]) -> UICollectionViewCell {
print(hit.count)
let cell: listItemCollectionViewCell
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hitCell", for: indexPath) as! listItemCollectionViewCell
cell.listItemLabel.text = hit["name"] as? String
print(hit)
cell.listItemPrice.text = hit["price"] as? String
if let strImage = hit["image_url"] as? String {
let baseUrl = "http:\(strImage)"
cell.listItemImg.contentMode = .scaleAspectFit
cell.listItemImg.kf.indicatorType = .activity
if URL(string: baseUrl) != nil {
let resource = ImageResource(downloadURL: URL(string: baseUrl)!, cacheKey: baseUrl)
cell.listItemImg.kf.setImage(with: resource, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
}
else{
cell.listItemImg.image = #imageLiteral(resourceName: "placeholder")
}
}
cell.wishListButton.addTarget(self, action: #selector(saleTappedButton(sender:)), for: .touchUpInside)
cell.listItemStarRating.starBorderColor = UIColor.lightGray
cell.listItemStarRating.starBorderWidth = 0.5
return cell
}
here is the image for algolia data displaying https://ibb.co/dudm8H and here is the image for categories page https://ibb.co/c5Ar8H after clicking particular category the selected category id will be passing in categories array mentioned in code
["[categories.level0:Women]", "[categories.level1:Women///Tops]", "[categories.level2:Women///Tops///Tees]"]
for facetFilters in query the facets will be passing in an facets array in code and is shown below
["categories.level0", "categories.level1", "categories.level2", "gometoo_seller", "style_bottom", "climate", "sleeve", "gender", "category_gear", "eco_collection", "pattern", "collar", "style_bags", "style_general", "is_trending", "erin_recommends", "format", "performance_fabric", "strap_bags", "features_bags", "activity", "material", "categories", "color", "is_new", "size", "price", "manufacturer", "price.BHD.default", "price.EGP.default", "price.EUR.default", "price.KWD.default", "price.OMR.default", "price.SAR.default", "price.USD.default", "price.AED.default"]
and algolia back end raw data is as shown below
index.search("", {
"hitsPerPage": "10",
"page": "0",
"analytics": "false",
"attributesToRetrieve": "*",
"facets": "[\"categories.level0\",\"categories.level1\",\"categories.level2\",\"activity\",\"category_gear\",\"climate\",\"color\",\"eco_collection\",\"erin_recommends\",\"features_bags\",\"format\",\"gender\",\"gometoo_seller\",\"is_new\",\"is_trending\",\"material\",\"pattern\",\"performance_fabric\",\"price.AED.default\",\"price.BHD.default\",\"price.EGP.default\",\"price.EUR.default\",\"price.KWD.default\",\"price.OMR.default\",\"price.SAR.default\",\"price.USD.default\",\"size\",\"strap_bags\",\"style_bags\",\"style_bottom\",\"style_general\"]",
"facetFilters": "[[\"categories.level2:Women /// Tops /// Tees\"],[\"categories.level1:Women /// Tops\"],[\"categories.level0:Women\"]]"
});
and in this page data to load default data is from products indices after making filter it needs to change but it resembles same old data
here is my complete data which i had been using still now using and any wrong am i doing here please let me know @spinach
I had placed breakpoints and checked after reaching InstantSearch.shared.searcher.index.search(query,
line it moves to index.swift in AlgoliaSearch client and later I tried to print cache key the data which was posting successfully printed but in searchCache it returns nil and later in if else loop it enters to else loop means indicating that no value for key in code and every time it goes to else loop an returning data in this what is searchCache can u explain me if possible ? @spinach
and here is my screenshot https://ibb.co/gpD37c
Okay so a couple of things @vamsikrishnasurathi:
1- Can you make sure to use this snippet of code in either viewDidLoad
or viewDidAppear
since this is where they are supposed to be (not inside index.search
):
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
2- When using InstantSearch library, you should try to refrain from using the functions available from index
or query
. Instead, use the higher level apis that are available for you from either InstantSearch Core or InstantSearch library. For example, instead of using facetFilters
, use the method addFacetRefinement
. Or even better, used our pre-packaged RefinementList which will give you filtering/faceting capabilities out of the box. Just follow the tutorial in this link in order to get started.
ok thanks for reply and will try to implement as you said @spinach
I am unable to use refinement controller because I am using a table view which to display sort results so unable to change and unable to use addFacetRefinement
because it only filters one word but I need to filter from array and later I changed my code and tried but unable to implement it and here is my whole code and in this page already I implemented search and sort in this and my whole data regarding this is shown below @spinach
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
here you asked me to post this code in viewDidLoad
or viewDidAppear
but after parsing api's only I am getting the appID,api key and indices so I posted in separate function and calling after api's data returned
override func viewDidLoad() {
super.viewDidLoad()
ActivityIndicator.startAnimating()
ActivityIndicator.hidesWhenStopped = true
searchBar.delegate = self
productListSortDownloadJsonWithURL()
searchBar.isUserInteractionEnabled = true
sortLabel.isUserInteractionEnabled = true
sortImage.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(sortTableFunction)))
sortLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(sortTableFunction)))
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
if receivedText == nil {
self.currencyCodesDownloadJsonWithURL()
self.facetsDownloadJsonWithURL()
applicationIdDownloadJsonWithURL()
}
else {
collectionViewLoadData()
}
}
func applicationIdDownloadJsonWithURL(){
let url = URL(string: applicationId)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String {
self.appId = jsonObj
DispatchQueue.main.async {
self.apiKeyDownloadJsonWithURL()
}
}
} catch {
print(error)
}
}
task.resume()
}
@IBAction func backbuttonAction(_ sender: Any) {
for viewController in (self.navigationController?.viewControllers)! {
if viewController is CategoriesViewController { // Here you need to change your class name instead of "WishListViewController"
self.navigationController?.popViewController(animated: true)
break
}else {
self.dismiss(animated: true, completion: nil)
}
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let abcViewController = storyboard.instantiateViewController(withIdentifier: "filterPage") as! filterPageViewController
abcViewController.delegate = self as! isAbleToReceiveData
self.present(abcViewController, animated: true, completion: nil)
}
func apiKeyDownloadJsonWithURL(){
let url = URL(string: apiKey)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String {
self.apiKEY = jsonObj
print(jsonObj)
DispatchQueue.main.async {
self.alogoliaIndicesDownloadJsonWithURL()
}
}
} catch {
print(error)
}
}
task.resume()
}
func pass(data: String) { //conforms to protocol
self.receivedText = data
print(data)
// searchBar.text = "\(data)"
}
func alogoliaIndicesDownloadJsonWithURL() {
let url = URL(string: algoliaIndicesName)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String {
print(jsonObj)
self.Indices = jsonObj
DispatchQueue.main.async {
self.collectionViewLoadData()
}
}
} catch {
print(error)
}
}
task.resume()
}
func collectionViewLoadData() {
if (self.appId != nil && self.apiKEY != nil && self.Indices != nil) {
InstantSearch.shared.configure(appID: "\(self.appId!)", apiKey: "\(self.apiKEY!)", index: "\(self.Indices!)en_products")
InstantSearch.shared.params.facets = self.facetsArray
print(categoriesArray)
InstantSearch.shared.params.facetFilters = self.categoriesArray
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
if receivedText != nil {
print(String(describing: receivedText!))
InstantSearch.shared.searchBar(searchBar, textDidChange: receivedText!)
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
}else {
print(facetsArray)
print(categoriesArray)
let query = Query()
query.facets = facetsArray
query.maxValuesPerFacet = 100
query.facetFilters = categoriesArray
InstantSearch.shared.searcher.index.search(query, requestOptions: nil, completionHandler: { (data, error) in
print(data)
self.listCollectionView.reloadData()
})
}
hitsCollectionViews = [self.listCollectionView]
ActivityIndicator.stopAnimating()
}
}
func productListSortDownloadJsonWithURL() {
let url = URL(string: sortIndicesURL)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments)
print(jsonObj)
let stringData = (jsonObj as AnyObject).data(using: String.Encoding.utf8.rawValue)! as NSData
let json = try JSONSerialization.jsonObject(with: stringData as Data, options: .mutableContainers)
print(json)
for (_, value) in json as! [String: Any] {
self.sortModel.append(SortArray.init(dict: value as! [String : Any]))
print(self.sortModel)
}
// print(self.sortModel)
DispatchQueue.main.async {
}
} catch {
print(error)
}
}
task.resume()
}
func currencyCodesDownloadJsonWithURL() {
let url = URL(string: currencyCodesURL)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String : Any] {
self.currencyModel = Currency(dict: jsonObj)
DispatchQueue.main.async {
for item in (self.currencyModel?.availableCurrencyCodes)! {
self.facetsArray.append("price.\(item).default")
}
}
print(self.facetsArray)
}
} catch {
print(error)
}
}
task.resume()
}
func facetsDownloadJsonWithURL(){
let url = URL(string: facetIndicesurl)!
var request = URLRequest(url: url as URL)
request.httpMethod = "GET"
request.addValue("Basic Z29tZXRvb2FkOm55UWREZ1ZYMWdYU1FkMmhHWEpN", forHTTPHeaderField: "Authorization")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil { print(error!); return }
do {
if let jsonObj = try! JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String {
let stringData = (jsonObj as AnyObject).data(using: String.Encoding.utf8.rawValue)! as NSData
let json = try JSONSerialization.jsonObject(with: stringData as Data, options: .mutableContainers)
print(json)
for (key, value) in json as! [String: Any] {
self.facetsModel.append(FacetsArray.init(dict: value as! [String : Any]))
}
for item in self.facetsModel {
self.facetsArray.append(item.attribute!)
}
print(self.facetsArray)
DispatchQueue.main.async {
}
}
} catch {
print(error)
}
}
task.resume()
}
open override func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath,
containing hit: [String : Any]) -> UICollectionViewCell {
print(hit)
let cell: listItemCollectionViewCell
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "hitCell", for: indexPath) as! listItemCollectionViewCell
cell.listItemLabel.text = hit["name"] as? String
if let strImage = hit["image_url"] as? String {
let baseUrl = "http:\(strImage)"
cell.listItemImg.contentMode = .scaleAspectFit
cell.listItemImg.kf.indicatorType = .activity
if URL(string: baseUrl) != nil {
let resource = ImageResource(downloadURL: URL(string: baseUrl)!, cacheKey: baseUrl)
cell.listItemImg.kf.setImage(with: resource, placeholder: nil, options: nil, progressBlock: nil, completionHandler: nil)
}
else{
cell.listItemImg.image = #imageLiteral(resourceName: "placeholder")
}
}
cell.wishListButton.addTarget(self, action: #selector(saleTappedButton(sender:)), for: .touchUpInside)
cell.listItemStarRating.starBorderColor = UIColor.lightGray
cell.listItemStarRating.starBorderWidth = 0.5
return cell
}
func doubleToStringDecimalPlacesWithDouble(number:Double, numberOfDecimalPlaces:Int) -> String {
return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
@objc func sortTableFunction() {
print("tap working")
if selected == true{
self.sortTableView.removeFromSuperview()
}else{
UIView.animate(withDuration: 1, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseInOut, animations: {
let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
let displayWidth: CGFloat = self.view.frame.width
let height = self.sortModel.count * 50
self.sortTableView = UITableView(frame: CGRect(x: 0, y: 127, width: Int(self.view.frame.width), height: height))
self.sortTableView.register(UITableViewCell.self, forCellReuseIdentifier: "sortCell")
self.sortTableView.delegate = self
self.sortTableView.dataSource = self
self.sortTableView.reloadData()
self.view.addSubview(self.sortTableView)
self.sortTableView.layoutIfNeeded()
self.sortTableView.isHidden = false
}, completion: nil)
self.selected = false
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sortModel.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sortCell", for: indexPath as IndexPath)
cell.textLabel!.text = sortModel[indexPath.row].sortLabel
if indexPath == selectedIndexPath {
cell.accessoryType = UITableViewCellAccessoryType.checkmark
} else {
cell.accessoryType = UITableViewCellAccessoryType.none
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
for item in self.sortModel {
if self.sortModel[indexPath.row].sortLabel == item.sortLabel {
self.attribute = item.attribute
self.sortDirection = item.sort
print(item.attribute)
}
}
InstantSearch.shared.configure(appID: "\(appId!)", apiKey: "\(apiKEY!)", index: "\(Indices!)en_products_\(self.attribute!)_\(self.sortDirection!)")
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
hitsCollectionViews = [self.listCollectionView]
tableView.deselectRow(at: indexPath, animated: true)
if indexPath == selectedIndexPath {
self.sortTableView.isHidden = true
self.sortTableView.removeFromSuperview()
}
let newCell = tableView.cellForRow(at: indexPath)
if newCell?.accessoryType == UITableViewCellAccessoryType.none {
newCell?.accessoryType = UITableViewCellAccessoryType.checkmark
}
let oldCell = tableView.cellForRow(at: selectedIndexPath)
if oldCell?.accessoryType == UITableViewCellAccessoryType.checkmark {
oldCell?.accessoryType = UITableViewCellAccessoryType.none
}
selectedIndexPath = indexPath // save the selected index path
self.selected = false
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.sortTableView.isHidden = true
self.sortTableView.removeFromSuperview()
}, completion: nil)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if self.sortTableView != nil{
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.sortTableView.removeFromSuperview()
}, completion: nil)
}
}
@objc func tapGesture(){
if self.sortTableView != nil{
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.sortTableView.removeFromSuperview()
}, completion: nil)
self.selected = false
}
}
@objc func saleTappedButton(sender: DOFavoriteButton) {
if sender.isSelected {
sender.deselect()
} else {
sender.select()
}
}
@IBAction func backButtonAction(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
}
and here posting parameters successfully printed but how to retrieve data after posting ?
1/indexes/gometoo_en_products/query_body_["params": "facetFilters=[%22[categories.level0:Women]%22,%22[categories.level1:Women%5C/%5C/%5C/Tops]%22,%22[categories.level2:Women%5C/%5C/%5C/Tops%5C/%5C/%5C/Tees]%22]&facets=[%22categories.level0%22,%22categories.level1%22,%22categories.level2%22,%22price.BHD.default%22,%22price.EGP.default%22,%22price.EUR.default%22,%22price.KWD.default%22,%22price.OMR.default%22,%22price.SAR.default%22,%22price.USD.default%22,%22price.AED.default%22,%22gometoo_seller%22,%22style_bottom%22,%22climate%22,%22sleeve%22,%22gender%22,%22category_gear%22,%22eco_collection%22,%22pattern%22,%22collar%22,%22style_bags%22,%22style_general%22,%22is_trending%22,%22erin_recommends%22,%22format%22,%22performance_fabric%22,%22strap_bags%22,%22features_bags%22,%22activity%22,%22material%22,%22categories%22,%22color%22,%22is_new%22,%22size%22,%22price%22,%22manufacturer%22]&maxValuesPerFacet=100"]
The data was returned successfully after filtering for facets and works fine now I need to pass the data to the collection view how to pass the data to the hit @spinach
Here in this function in which data is shown here the filtered data I got from facetsInstantSearch.shared.searcher.index.search(query, requestOptions: nil, completionHandler: { (data, error) in
is printed in data shown below now I need to pass this data to the hit so that I can able to show it on collection view
here is my code
func collectionViewLoadData() {
if (self.appId != nil && self.apiKEY != nil && self.Indices != nil) {
InstantSearch.shared.configure(appID: "\(self.appId!)", apiKey: "\(self.apiKEY!)", index: "\(self.Indices!)en_products")
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
if receivedText != nil {
print(String(describing: receivedText!))
InstantSearch.shared.searchBar(searchBar, textDidChange: receivedText!)
InstantSearch.shared.params.attributesToRetrieve = ["*"]
InstantSearch.shared.registerAllWidgets(in: self.view)
}else {
let query = Query()
query.facets = facetsArray
query.facetFilters = categoriesArray
query.hitsPerPage = 100
InstantSearch.shared.searcher.index.search(query, requestOptions: nil, completionHandler: { (data, error) in
print(data)
})
}
hitsCollectionViews = [self.listCollectionView]
ActivityIndicator.stopAnimating()
}
}
Hi @vamsikrishnasurathi,
If you're asking about how to access the filters, you can use something like InstantSearch.shared.params.filters
or InstantSearch.shared.params.facets
.
If you're not able to make the filters work, have a look at refinementList guide, or if you want more control, InstantSearch.shared.searcher
and then use the filtering methods that are mentioned in this guide
Any how thanks for suggestions at last I got by using algolia search client
Here I am using the algolia for the first time to display the categories selected id to pass and load data in list page according to it and here I passed the selected data to the list page but here unable to load the data required for selected category and got crashed in
index.search
line please help me how to resolve this ?Here is my selected categories array data which I was passing from my categories page
["[categories.level0:Men]", "[categories.level1:Men///Tops]", "[categories.level2:Men///Tops///Tees]"]
and below is my facets array data
["categories.level0", "categories.level1", "categories.level2", "gometoo_seller", "style_bottom", "climate", "sleeve", "gender", "category_gear", "eco_collection", "pattern", "collar", "style_bags", "style_general", "is_trending", "erin_recommends", "format", "performance_fabric", "strap_bags", "features_bags", "activity", "material", "categories", "color", "is_new", "size", "price", "manufacturer", "price.BHD.default", "price.EGP.default", "price.EUR.default", "price.KWD.default", "price.OMR.default", "price.SAR.default", "price.USD.default", "price.AED.default"]
here is my algolia back end data
and the code for this is