algolia / algolia/algoliasearch-helper-flutter
How to display facets with count
- Dominant language
- Dart
- Stars
- 27
- Forks
- 21
- Avg merge
- 1h 19m
- Merged PRs (30d)
- 1
Description
I'm trying to get the list of facet that I've configured as describe [here](https://www.algolia.com/doc/guides/building-search-ui/ui-and-ux-patterns/facet-display/js/?client=javascript). I use the new official Algolia package along with the unofficial for settings. I thought that use the official package would change the response. Despite in the console browser every thing is display as attended, the searchResponse.facets is always empty. Check the code below.
```import 'dart:async';
import 'dart:io';
import 'package:algolia/algolia.dart';
import 'package:algolia_helper_flutter/algolia_helper_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:masterecommerce/src/constants/app_sizes.dart';
import 'package:masterecommerce/src/exceptions/app_exception.dart';
import 'package:masterecommerce/src/features/menu/presentation/search_header.dart';
import 'package:masterecommerce/src/features/products/domain/algolia_output.dart';
import 'package:masterecommerce/src/features/products/domain/algolia_params.dart';
import '../constants/credentials.dart';
import '../features/products/domain/product.dart';
import 'firestore_service.dart';
final searchResponseProvider = StateProvider.autoDispose((ref) {
return SearchResponse({});
});
final searchStateProvider = StateProvider.autoDispose((ref) {
return const SearchState(indexName: kIndexName);
});
final algoliaInputProvider = StateProvider.autoDispose((ref) {
return const AlgoliaInput();
});
final algoliaControllerProvider = StateNotifierProvider.autoDispose<
AlgoliaController, AsyncValue>>((ref) {
return AlgoliaController(
ref: ref, algoliaInput: ref.watch(algoliaInputProvider));
});
final algoliaControllerSearchProvider = StateNotifierProvider.autoDispose<
AlgoliaController, AsyncValue>>((ref) {
return AlgoliaController(
ref: ref,
algoliaInput: AlgoliaInput(
query: ref.watch(currentQuerySearchProvider), hitsPerPage: 3));
});
class AlgoliaController extends StateNotifier>> {
StreamSubscription? subResponses;
StreamSubscription? subSearchState;
late HitsSearcher searcher;
late Algolia algoliaForSettings;
final Ref ref;
final AlgoliaInput algoliaInput;
AlgoliaController({required this.ref, required this.algoliaInput})
: super(const AsyncLoading()) {
algoliaForSettings = const Algolia.init(
applicationId: algoliaKeyAppId, apiKey: algoliaKeyCustom);
searcher = HitsSearcher(
applicationID: algoliaKeyAppId,
apiKey: algoliaKeyCustom,
indexName: kIndexName,
);
subResponses = searcher.responses.handleError((onError) {
print(onError);
state = AsyncError(onError);
}).listen((searchResponse) {
print(searchResponse.facets);
print(searchResponse.raw["facets"]);
ref.read(searchResponseProvider.state).update((state) => searchResponse);
final products = searchResponse.hits
.map((e) => Product.fromMapAlgolia(e.cast()))
.toList();
if (mounted) {
state = AsyncValue>.data(products);
}
});
subSearchState = searcher.state.handleError((onError) {
print(onError);
state = AsyncError(onError);
}).listen((searchState) {
ref.read(searchStateProvider.state).update((state) => searchState);
});
_newAlgoliaState(algoliaInput: algoliaInput);
}
@override
void dispose() {
searcher.dispose();
subResponses?.cancel();
subSearchState?.cancel();
super.dispose();
}
Future _newAlgoliaState({required AlgoliaInput algoliaInput}) async {
state = const AsyncLoading();
final algoliaOutput = algoliaInput.toAlgoliaOutput();
await _setAlgoliaRanking(algoliaOutput: algoliaOutput);
if (!mounted) {
return;
}
searcher.connectFilterState(algoliaOutput.filterState);
searcher.applyState((state) => algoliaOutput.toSearchState());
}
Future _setAlgoliaRanking(
{required AlgoliaOutput algoliaOutput}) async {
AlgoliaIndexReference algoliaIndexReference =
algoliaForSettings.instance.index("products");
final ranking = algoliaOutput.ranking;
if (ranking != null && ranking.isNotEmpty) {
AlgoliaTask algoliaTask =
await algoliaIndexReference.settings.setRanking([
...ranking,
"typo",
"geo",
"words",
"filters",
"proximity",
"attribute",
"exact",
"custom",
]).setSettings();
await algoliaTask
.waitTask()
.timeout(const Duration(seconds: timeOutSecond))
.catchError((onError) {
if (onError is SocketException) {
throw const AppException.noInternet();
} else if (onError is TimeoutException) {
throw const AppException.timeOut();
} else {
throw const AppException.unknown();
}
});
}
final customRanking = algoliaOutput.customRanking;
if (customRanking != null && customRanking.isNotEmpty) {
final AlgoliaTask algoliaTask = await algoliaIndexReference.settings
.setCustomRanking(customRanking)
.setSettings();
await algoliaTask
.waitTask()
.timeout(const Duration(seconds: timeOutSecond))
.catchError((onError) {
if (onError is SocketException) {
throw const AppException.noInternet();
} else if (onError is TimeoutException) {
throw const AppException.timeOut();
} else {
throw const AppException.unknown();
}
});
}
}
}
```
Contributor guide
Research direction
Start by reproducing the response from the searcher.responses listener and inspect SearchResponse.facets alongside raw["facets"]. Trace the state setup through _newAlgoliaState, connectFilterState, and applyState, and compare it with the Algolia index settings configured in _setAlgoliaRanking. Done means configured facets and their counts are available in the search response.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart, flutter
- Domain
- mobile-dev, search
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100